mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-25 22:14:32 +00:00
Improve TorrentModel class.
This commit is contained in:
parent
7699b7ce6f
commit
64c8f61bb1
@ -59,6 +59,7 @@ struct SessionPrivate
|
|||||||
|
|
||||||
virtual void handleTorrentRatioLimitChanged(BitTorrent::TorrentHandle *const torrent) = 0;
|
virtual void handleTorrentRatioLimitChanged(BitTorrent::TorrentHandle *const torrent) = 0;
|
||||||
virtual void handleTorrentSavePathChanged(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 handleTorrentMetadataReceived(BitTorrent::TorrentHandle *const torrent) = 0;
|
||||||
virtual void handleTorrentPaused(BitTorrent::TorrentHandle *const torrent) = 0;
|
virtual void handleTorrentPaused(BitTorrent::TorrentHandle *const torrent) = 0;
|
||||||
virtual void handleTorrentResumed(BitTorrent::TorrentHandle *const torrent) = 0;
|
virtual void handleTorrentResumed(BitTorrent::TorrentHandle *const torrent) = 0;
|
||||||
|
@ -1631,6 +1631,11 @@ void Session::handleTorrentSavePathChanged(TorrentHandle *const torrent)
|
|||||||
emit torrentSavePathChanged(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)
|
void Session::handleTorrentTrackersAdded(TorrentHandle *const torrent, const QList<TrackerEntry> &newTrackers)
|
||||||
{
|
{
|
||||||
foreach (const TrackerEntry &newTracker, newTrackers)
|
foreach (const TrackerEntry &newTracker, newTrackers)
|
||||||
|
@ -195,6 +195,7 @@ namespace BitTorrent
|
|||||||
void torrentFinished(BitTorrent::TorrentHandle *const torrent);
|
void torrentFinished(BitTorrent::TorrentHandle *const torrent);
|
||||||
void torrentFinishedChecking(BitTorrent::TorrentHandle *const torrent);
|
void torrentFinishedChecking(BitTorrent::TorrentHandle *const torrent);
|
||||||
void torrentSavePathChanged(BitTorrent::TorrentHandle *const torrent);
|
void torrentSavePathChanged(BitTorrent::TorrentHandle *const torrent);
|
||||||
|
void torrentLabelChanged(BitTorrent::TorrentHandle *const torrent, const QString &oldLabel);
|
||||||
void allTorrentsFinished();
|
void allTorrentsFinished();
|
||||||
void metadataLoaded(const BitTorrent::TorrentInfo &info);
|
void metadataLoaded(const BitTorrent::TorrentInfo &info);
|
||||||
void torrentMetadataLoaded(BitTorrent::TorrentHandle *const torrent);
|
void torrentMetadataLoaded(BitTorrent::TorrentHandle *const torrent);
|
||||||
@ -289,6 +290,7 @@ namespace BitTorrent
|
|||||||
QString tempPath() const;
|
QString tempPath() const;
|
||||||
void handleTorrentRatioLimitChanged(TorrentHandle *const torrent);
|
void handleTorrentRatioLimitChanged(TorrentHandle *const torrent);
|
||||||
void handleTorrentSavePathChanged(TorrentHandle *const torrent);
|
void handleTorrentSavePathChanged(TorrentHandle *const torrent);
|
||||||
|
void handleTorrentLabelChanged(TorrentHandle *const torrent, const QString &oldLabel);
|
||||||
void handleTorrentMetadataReceived(TorrentHandle *const torrent);
|
void handleTorrentMetadataReceived(TorrentHandle *const torrent);
|
||||||
void handleTorrentPaused(TorrentHandle *const torrent);
|
void handleTorrentPaused(TorrentHandle *const torrent);
|
||||||
void handleTorrentResumed(TorrentHandle *const torrent);
|
void handleTorrentResumed(TorrentHandle *const torrent);
|
||||||
|
@ -969,6 +969,14 @@ int TorrentHandle::timeSinceDownload() const
|
|||||||
return m_nativeStatus.time_since_download;
|
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
|
int TorrentHandle::downloadLimit() const
|
||||||
{
|
{
|
||||||
SAFE_RETURN(int, download_limit, -1)
|
SAFE_RETURN(int, download_limit, -1)
|
||||||
@ -1117,9 +1125,11 @@ void TorrentHandle::setName(const QString &name)
|
|||||||
void TorrentHandle::setLabel(const QString &label)
|
void TorrentHandle::setLabel(const QString &label)
|
||||||
{
|
{
|
||||||
if (m_label != label) {
|
if (m_label != label) {
|
||||||
|
QString oldLabel = m_label;
|
||||||
m_label = label;
|
m_label = label;
|
||||||
m_needSaveResumeData = true;
|
m_needSaveResumeData = true;
|
||||||
adjustSavePath();
|
adjustSavePath();
|
||||||
|
m_session->handleTorrentLabelChanged(this, oldLabel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,6 +241,7 @@ namespace BitTorrent
|
|||||||
QDateTime completedTime() const;
|
QDateTime completedTime() const;
|
||||||
int timeSinceUpload() const;
|
int timeSinceUpload() const;
|
||||||
int timeSinceDownload() const;
|
int timeSinceDownload() const;
|
||||||
|
int timeSinceActivity() const;
|
||||||
int downloadLimit() const;
|
int downloadLimit() const;
|
||||||
int uploadLimit() const;
|
int uploadLimit() const;
|
||||||
bool superSeeding() const;
|
bool superSeeding() const;
|
||||||
|
@ -332,8 +332,6 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
connect(executable_watcher, SIGNAL(fileChanged(QString)), this, SLOT(notifyOfUpdate(QString)));
|
connect(executable_watcher, SIGNAL(fileChanged(QString)), this, SLOT(notifyOfUpdate(QString)));
|
||||||
executable_watcher->addPath(qApp->applicationFilePath());
|
executable_watcher->addPath(qApp->applicationFilePath());
|
||||||
|
|
||||||
// Populate the transfer list
|
|
||||||
transferList->getSourceModel()->populate();
|
|
||||||
transferList->setFocus();
|
transferList->setFocus();
|
||||||
|
|
||||||
// Update the number of torrents (tab)
|
// Update the number of torrents (tab)
|
||||||
|
@ -97,7 +97,6 @@ public slots:
|
|||||||
void saveSettings();
|
void saveSettings();
|
||||||
void reloadPreferences();
|
void reloadPreferences();
|
||||||
void openDoubleClickedFile(const QModelIndex &);
|
void openDoubleClickedFile(const QModelIndex &);
|
||||||
void updateSavePath(BitTorrent::TorrentHandle *const torrent);
|
|
||||||
void loadTrackers(BitTorrent::TorrentHandle *const torrent);
|
void loadTrackers(BitTorrent::TorrentHandle *const torrent);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -126,6 +125,7 @@ private:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void filterText(const QString& filter);
|
void filterText(const QString& filter);
|
||||||
|
void updateSavePath(BitTorrent::TorrentHandle *const torrent);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PROPERTIESWIDGET_H
|
#endif // PROPERTIESWIDGET_H
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt4 and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2010 Christophe Dumez
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -34,110 +35,315 @@
|
|||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
|
||||||
#include "core/bittorrent/session.h"
|
#include "core/bittorrent/session.h"
|
||||||
|
#include "core/bittorrent/torrenthandle.h"
|
||||||
#include "core/torrentfilter.h"
|
#include "core/torrentfilter.h"
|
||||||
#include "core/utils/fs.h"
|
#include "core/utils/fs.h"
|
||||||
#include "torrentmodel.h"
|
#include "torrentmodel.h"
|
||||||
|
|
||||||
namespace {
|
static QIcon getIconByState(BitTorrent::TorrentState state);
|
||||||
QIcon get_paused_icon() {
|
static QColor getColorByState(BitTorrent::TorrentState state);
|
||||||
static QIcon cached = QIcon(":/icons/skin/paused.png");
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon get_queued_icon() {
|
static QIcon getPausedIcon();
|
||||||
static QIcon cached = QIcon(":/icons/skin/queued.png");
|
static QIcon getQueuedIcon();
|
||||||
return cached;
|
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 bool isDarkTheme();
|
||||||
static QIcon cached = QIcon(":/icons/skin/downloading.png");
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon get_stalled_downloading_icon() {
|
// TorrentModel
|
||||||
static QIcon cached = QIcon(":/icons/skin/stalledDL.png");
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
QIcon get_uploading_icon() {
|
TorrentModel::TorrentModel(QObject *parent)
|
||||||
static QIcon cached = QIcon(":/icons/skin/uploading.png");
|
: QAbstractListModel(parent)
|
||||||
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()
|
|
||||||
{
|
{
|
||||||
QPalette pal = QApplication::palette();
|
// Load the torrents
|
||||||
// QPalette::Base is used for the background of the Treeview
|
foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents())
|
||||||
QColor color = pal.color(QPalette::Active, QPalette::Base);
|
addTorrent(torrent);
|
||||||
return (color.lightness() < 127);
|
|
||||||
}
|
// 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)
|
int TorrentModel::rowCount(const QModelIndex &index) const
|
||||||
: m_torrent(torrent)
|
|
||||||
{
|
{
|
||||||
|
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) {
|
switch (state) {
|
||||||
case BitTorrent::TorrentState::Downloading:
|
case BitTorrent::TorrentState::Downloading:
|
||||||
case BitTorrent::TorrentState::ForcedDownloading:
|
case BitTorrent::TorrentState::ForcedDownloading:
|
||||||
case BitTorrent::TorrentState::DownloadingMetadata:
|
case BitTorrent::TorrentState::DownloadingMetadata:
|
||||||
return get_downloading_icon();
|
return getDownloadingIcon();
|
||||||
case BitTorrent::TorrentState::Allocating:
|
case BitTorrent::TorrentState::Allocating:
|
||||||
case BitTorrent::TorrentState::StalledDownloading:
|
case BitTorrent::TorrentState::StalledDownloading:
|
||||||
return get_stalled_downloading_icon();
|
return getStalledDownloadingIcon();
|
||||||
case BitTorrent::TorrentState::StalledUploading:
|
case BitTorrent::TorrentState::StalledUploading:
|
||||||
return get_stalled_uploading_icon();
|
return getStalledUploadingIcon();
|
||||||
case BitTorrent::TorrentState::Uploading:
|
case BitTorrent::TorrentState::Uploading:
|
||||||
case BitTorrent::TorrentState::ForcedUploading:
|
case BitTorrent::TorrentState::ForcedUploading:
|
||||||
return get_uploading_icon();
|
return getUploadingIcon();
|
||||||
case BitTorrent::TorrentState::PausedDownloading:
|
case BitTorrent::TorrentState::PausedDownloading:
|
||||||
return get_paused_icon();
|
return getPausedIcon();
|
||||||
case BitTorrent::TorrentState::PausedUploading:
|
case BitTorrent::TorrentState::PausedUploading:
|
||||||
return get_completed_icon();
|
return getCompletedIcon();
|
||||||
case BitTorrent::TorrentState::QueuedDownloading:
|
case BitTorrent::TorrentState::QueuedDownloading:
|
||||||
case BitTorrent::TorrentState::QueuedUploading:
|
case BitTorrent::TorrentState::QueuedUploading:
|
||||||
return get_queued_icon();
|
return getQueuedIcon();
|
||||||
case BitTorrent::TorrentState::CheckingDownloading:
|
case BitTorrent::TorrentState::CheckingDownloading:
|
||||||
case BitTorrent::TorrentState::CheckingUploading:
|
case BitTorrent::TorrentState::CheckingUploading:
|
||||||
return get_checking_icon();
|
return getCheckingIcon();
|
||||||
case BitTorrent::TorrentState::Unknown:
|
case BitTorrent::TorrentState::Unknown:
|
||||||
case BitTorrent::TorrentState::Error:
|
case BitTorrent::TorrentState::Error:
|
||||||
return get_error_icon();
|
return getErrorIcon();
|
||||||
default:
|
default:
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
return get_error_icon();
|
return getErrorIcon();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor TorrentModelItem::getColorByState(BitTorrent::TorrentState state)
|
QColor getColorByState(BitTorrent::TorrentState state)
|
||||||
{
|
{
|
||||||
bool dark = isDarkTheme();
|
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;
|
static QIcon cached = QIcon(":/icons/skin/paused.png");
|
||||||
if (role != Qt::DisplayRole) return false;
|
return cached;
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant TorrentModelItem::data(int column, int role) const
|
QIcon getQueuedIcon()
|
||||||
{
|
{
|
||||||
if ((role == Qt::DecorationRole) && (column == TR_NAME))
|
static QIcon cached = QIcon(":/icons/skin/queued.png");
|
||||||
return getIconByState(state());
|
return cached;
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BitTorrent::TorrentHandle *TorrentModelItem::torrentHandle() const
|
QIcon getDownloadingIcon()
|
||||||
{
|
{
|
||||||
return m_torrent;
|
static QIcon cached = QIcon(":/icons/skin/downloading.png");
|
||||||
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TORRENT MODEL
|
QIcon getStalledDownloadingIcon()
|
||||||
|
|
||||||
TorrentModel::TorrentModel(QObject *parent)
|
|
||||||
: QAbstractListModel(parent)
|
|
||||||
{
|
{
|
||||||
|
static QIcon cached = QIcon(":/icons/skin/stalledDL.png");
|
||||||
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentModel::populate()
|
QIcon getUploadingIcon()
|
||||||
{
|
{
|
||||||
// Load the torrents
|
static QIcon cached = QIcon(":/icons/skin/uploading.png");
|
||||||
foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents())
|
return cached;
|
||||||
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)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TorrentModel::~TorrentModel() {
|
QIcon getStalledUploadingIcon()
|
||||||
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
|
|
||||||
{
|
{
|
||||||
if (orientation == Qt::Horizontal) {
|
static QIcon cached = QIcon(":/icons/skin/stalledUP.png");
|
||||||
if (role == Qt::DisplayRole) {
|
return cached;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant TorrentModel::data(const QModelIndex &index, int role) const
|
QIcon getCompletedIcon()
|
||||||
{
|
{
|
||||||
if (!index.isValid()) return QVariant();
|
static QIcon cached = QIcon(":/icons/skin/completed.png");
|
||||||
|
return cached;
|
||||||
if (index.row() >= 0 && index.row() < rowCount() && index.column() >= 0 && index.column() < columnCount())
|
|
||||||
return m_items[index.row()]->data(index.column(), role);
|
|
||||||
|
|
||||||
return QVariant();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TorrentModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
QIcon getCheckingIcon()
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << value;
|
static QIcon cached = QIcon(":/icons/skin/checking.png");
|
||||||
if (!index.isValid() || (role != Qt::DisplayRole)) return false;
|
return cached;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TorrentModel::torrentRow(const BitTorrent::InfoHash &hash) const
|
QIcon getErrorIcon()
|
||||||
{
|
{
|
||||||
int row = 0;
|
static QIcon cached = QIcon(":/icons/skin/error.png");
|
||||||
|
return cached;
|
||||||
foreach (TorrentModelItem *const item, m_items) {
|
|
||||||
if (item->hash() == hash) return row;
|
|
||||||
++row;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentModel::addTorrent(BitTorrent::TorrentHandle *const torrent)
|
bool isDarkTheme()
|
||||||
{
|
{
|
||||||
if (torrentRow(torrent->hash()) < 0) {
|
QPalette pal = QApplication::palette();
|
||||||
beginInsertTorrent(m_items.size());
|
// QPalette::Base is used for the background of the Treeview
|
||||||
TorrentModelItem *item = new TorrentModelItem(torrent);
|
QColor color = pal.color(QPalette::Active, QPalette::Base);
|
||||||
connect(item, SIGNAL(labelChanged(QString, QString)), SLOT(handleTorrentLabelChange(QString, QString)));
|
return (color.lightness() < 127);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Bittorrent Client using Qt4 and libtorrent.
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
* Copyright (C) 2010 Christophe Dumez
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -34,35 +35,11 @@
|
|||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
||||||
#include "core/bittorrent/torrenthandle.h"
|
namespace BitTorrent
|
||||||
|
{
|
||||||
class QIcon;
|
class InfoHash;
|
||||||
|
class TorrentHandle;
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TorrentModel : public QAbstractListModel
|
class TorrentModel : public QAbstractListModel
|
||||||
{
|
{
|
||||||
@ -70,39 +47,59 @@ class TorrentModel : public QAbstractListModel
|
|||||||
Q_DISABLE_COPY(TorrentModel)
|
Q_DISABLE_COPY(TorrentModel)
|
||||||
|
|
||||||
public:
|
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);
|
explicit TorrentModel(QObject *parent = 0);
|
||||||
~TorrentModel();
|
|
||||||
inline int rowCount(const QModelIndex& index = QModelIndex()) const { Q_UNUSED(index); return m_items.size(); }
|
int rowCount(const QModelIndex& index = QModelIndex()) const;
|
||||||
int columnCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return TorrentModelItem::NB_COLUMNS; }
|
int columnCount(const QModelIndex &parent=QModelIndex()) const;
|
||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole);
|
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole);
|
||||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
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;
|
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||||
void populate();
|
|
||||||
|
|
||||||
signals:
|
BitTorrent::TorrentHandle *torrentHandle(const QModelIndex &index) const;
|
||||||
void torrentAdded(TorrentModelItem *torrentItem);
|
|
||||||
void torrentAboutToBeRemoved(TorrentModelItem *torrentItem);
|
|
||||||
void torrentChangedLabel(TorrentModelItem *torrentItem, QString previous, QString current);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void addTorrent(BitTorrent::TorrentHandle *const torrent);
|
void addTorrent(BitTorrent::TorrentHandle *const torrent);
|
||||||
void notifyTorrentChanged(int row);
|
|
||||||
void handleTorrentLabelChange(QString previous, QString current);
|
|
||||||
void handleTorrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent);
|
void handleTorrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent);
|
||||||
void handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const torrent);
|
void handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const torrent);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void beginInsertTorrent(int row);
|
QList<BitTorrent::TorrentHandle *> m_torrents;
|
||||||
void endInsertTorrent();
|
|
||||||
void beginRemoveTorrent(int row);
|
|
||||||
void endRemoveTorrent();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QList<TorrentModelItem*> m_items;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TORRENTMODEL_H
|
#endif // TORRENTMODEL_H
|
||||||
|
@ -56,27 +56,27 @@ void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem
|
|||||||
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
|
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
|
||||||
painter->save();
|
painter->save();
|
||||||
switch(index.column()) {
|
switch(index.column()) {
|
||||||
case TorrentModelItem::TR_AMOUNT_DOWNLOADED:
|
case TorrentModel::TR_AMOUNT_DOWNLOADED:
|
||||||
case TorrentModelItem::TR_AMOUNT_UPLOADED:
|
case TorrentModel::TR_AMOUNT_UPLOADED:
|
||||||
case TorrentModelItem::TR_AMOUNT_DOWNLOADED_SESSION:
|
case TorrentModel::TR_AMOUNT_DOWNLOADED_SESSION:
|
||||||
case TorrentModelItem::TR_AMOUNT_UPLOADED_SESSION:
|
case TorrentModel::TR_AMOUNT_UPLOADED_SESSION:
|
||||||
case TorrentModelItem::TR_AMOUNT_LEFT:
|
case TorrentModel::TR_AMOUNT_LEFT:
|
||||||
case TorrentModelItem::TR_COMPLETED:
|
case TorrentModel::TR_COMPLETED:
|
||||||
case TorrentModelItem::TR_SIZE:
|
case TorrentModel::TR_SIZE:
|
||||||
case TorrentModelItem::TR_TOTAL_SIZE: {
|
case TorrentModel::TR_TOTAL_SIZE: {
|
||||||
QItemDelegate::drawBackground(painter, opt, index);
|
QItemDelegate::drawBackground(painter, opt, index);
|
||||||
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
|
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
|
||||||
QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::friendlyUnit(index.data().toLongLong()));
|
QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::friendlyUnit(index.data().toLongLong()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TorrentModelItem::TR_ETA: {
|
case TorrentModel::TR_ETA: {
|
||||||
QItemDelegate::drawBackground(painter, opt, index);
|
QItemDelegate::drawBackground(painter, opt, index);
|
||||||
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
|
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
|
||||||
QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::userFriendlyDuration(index.data().toLongLong()));
|
QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::userFriendlyDuration(index.data().toLongLong()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TorrentModelItem::TR_SEEDS:
|
case TorrentModel::TR_SEEDS:
|
||||||
case TorrentModelItem::TR_PEERS: {
|
case TorrentModel::TR_PEERS: {
|
||||||
QString display = QString::number(index.data().toLongLong());
|
QString display = QString::number(index.data().toLongLong());
|
||||||
qlonglong total = index.data(Qt::UserRole).toLongLong();
|
qlonglong total = index.data(Qt::UserRole).toLongLong();
|
||||||
if (total > 0) {
|
if (total > 0) {
|
||||||
@ -88,7 +88,7 @@ void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem
|
|||||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, display);
|
QItemDelegate::drawDisplay(painter, opt, opt.rect, display);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TorrentModelItem::TR_STATUS: {
|
case TorrentModel::TR_STATUS: {
|
||||||
const int state = index.data().toInt();
|
const int state = index.data().toInt();
|
||||||
QString display;
|
QString display;
|
||||||
switch(state) {
|
switch(state) {
|
||||||
@ -138,23 +138,23 @@ void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem
|
|||||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, display);
|
QItemDelegate::drawDisplay(painter, opt, opt.rect, display);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TorrentModelItem::TR_UPSPEED:
|
case TorrentModel::TR_UPSPEED:
|
||||||
case TorrentModelItem::TR_DLSPEED: {
|
case TorrentModel::TR_DLSPEED: {
|
||||||
QItemDelegate::drawBackground(painter, opt, index);
|
QItemDelegate::drawBackground(painter, opt, index);
|
||||||
const qulonglong speed = index.data().toULongLong();
|
const qulonglong speed = index.data().toULongLong();
|
||||||
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
|
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
|
||||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, Utils::Misc::friendlyUnit(speed)+tr("/s", "/second (.i.e per second)"));
|
QItemDelegate::drawDisplay(painter, opt, opt.rect, Utils::Misc::friendlyUnit(speed)+tr("/s", "/second (.i.e per second)"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TorrentModelItem::TR_UPLIMIT:
|
case TorrentModel::TR_UPLIMIT:
|
||||||
case TorrentModelItem::TR_DLLIMIT: {
|
case TorrentModel::TR_DLLIMIT: {
|
||||||
QItemDelegate::drawBackground(painter, opt, index);
|
QItemDelegate::drawBackground(painter, opt, index);
|
||||||
const qlonglong limit = index.data().toLongLong();
|
const qlonglong limit = index.data().toLongLong();
|
||||||
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
|
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("∞"));
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case TorrentModelItem::TR_TIME_ELAPSED: {
|
case TorrentModel::TR_TIME_ELAPSED: {
|
||||||
QItemDelegate::drawBackground(painter, opt, index);
|
QItemDelegate::drawBackground(painter, opt, index);
|
||||||
QString txt = Utils::Misc::userFriendlyDuration(index.data().toLongLong());
|
QString txt = Utils::Misc::userFriendlyDuration(index.data().toLongLong());
|
||||||
qlonglong seeding_time = index.data(Qt::UserRole).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);
|
QItemDelegate::drawDisplay(painter, opt, opt.rect, txt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TorrentModelItem::TR_ADD_DATE:
|
case TorrentModel::TR_ADD_DATE:
|
||||||
case TorrentModelItem::TR_SEED_DATE:
|
case TorrentModel::TR_SEED_DATE:
|
||||||
QItemDelegate::drawBackground(painter, opt, index);
|
QItemDelegate::drawBackground(painter, opt, index);
|
||||||
QItemDelegate::drawDisplay(painter, opt, opt.rect, index.data().toDateTime().toLocalTime().toString(Qt::DefaultLocaleShortDate));
|
QItemDelegate::drawDisplay(painter, opt, opt.rect, index.data().toDateTime().toLocalTime().toString(Qt::DefaultLocaleShortDate));
|
||||||
break;
|
break;
|
||||||
case TorrentModelItem::TR_RATIO_LIMIT:
|
case TorrentModel::TR_RATIO_LIMIT:
|
||||||
case TorrentModelItem::TR_RATIO: {
|
case TorrentModel::TR_RATIO: {
|
||||||
QItemDelegate::drawBackground(painter, opt, index);
|
QItemDelegate::drawBackground(painter, opt, index);
|
||||||
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
|
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
|
||||||
const qreal ratio = index.data().toDouble();
|
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));
|
((ratio == -1) || (ratio > BitTorrent::TorrentHandle::MAX_RATIO)) ? QString::fromUtf8("∞") : Utils::String::fromDouble(ratio, 2));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TorrentModelItem::TR_PRIORITY: {
|
case TorrentModel::TR_PRIORITY: {
|
||||||
const int priority = index.data().toInt();
|
const int priority = index.data().toInt();
|
||||||
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
|
opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
|
||||||
if (priority > 0)
|
if (priority > 0)
|
||||||
@ -188,7 +188,7 @@ void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TorrentModelItem::TR_PROGRESS: {
|
case TorrentModel::TR_PROGRESS: {
|
||||||
QStyleOptionProgressBarV2 newopt;
|
QStyleOptionProgressBarV2 newopt;
|
||||||
qreal progress = index.data().toDouble()*100.;
|
qreal progress = index.data().toDouble()*100.;
|
||||||
newopt.rect = opt.rect;
|
newopt.rect = opt.rect;
|
||||||
@ -211,7 +211,7 @@ void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TorrentModelItem::TR_LAST_ACTIVITY: {
|
case TorrentModel::TR_LAST_ACTIVITY: {
|
||||||
QString elapsedString;
|
QString elapsedString;
|
||||||
long long elapsed = index.data().toLongLong();
|
long long elapsed = index.data().toLongLong();
|
||||||
QItemDelegate::drawBackground(painter, opt, index);
|
QItemDelegate::drawBackground(painter, opt, index);
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
#include "core/torrentfilter.h"
|
#include "core/torrentfilter.h"
|
||||||
#include "core/bittorrent/trackerentry.h"
|
#include "core/bittorrent/trackerentry.h"
|
||||||
#include "core/bittorrent/session.h"
|
#include "core/bittorrent/session.h"
|
||||||
|
#include "core/bittorrent/torrenthandle.h"
|
||||||
#include "core/net/downloadmanager.h"
|
#include "core/net/downloadmanager.h"
|
||||||
#include "core/net/downloadhandler.h"
|
#include "core/net/downloadhandler.h"
|
||||||
#include "core/utils/misc.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(customContextMenuRequested(QPoint)), SLOT(showMenu(QPoint)));
|
||||||
connect(this, SIGNAL(currentRowChanged(int)), SLOT(applyFilter(int)));
|
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
|
QSize FiltersBase::sizeHint() const
|
||||||
@ -165,9 +167,9 @@ void StatusFiltersWidget::applyFilter(int row)
|
|||||||
transferList->applyStatusFilter(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)
|
LabelFiltersList::LabelFiltersList(QWidget *parent, TransferListWidget *transferList)
|
||||||
: FiltersBase(parent, transferList)
|
: FiltersBase(parent, transferList)
|
||||||
@ -175,7 +177,8 @@ LabelFiltersList::LabelFiltersList(QWidget *parent, TransferListWidget *transfer
|
|||||||
, m_totalLabeled(0)
|
, m_totalLabeled(0)
|
||||||
{
|
{
|
||||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
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
|
// Add Label filters
|
||||||
QListWidgetItem *allLabels = new QListWidgetItem(this);
|
QListWidgetItem *allLabels = new QListWidgetItem(this);
|
||||||
@ -309,12 +312,12 @@ void LabelFiltersList::removeUnusedLabels()
|
|||||||
updateGeometry();
|
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(oldLabel), qPrintable(torrent->label()));
|
||||||
qDebug("Torrent label changed from %s to %s", qPrintable(old_label), qPrintable(new_label));
|
removeItem(oldLabel);
|
||||||
removeItem(old_label);
|
QString newLabel = torrent->label();
|
||||||
addItem(new_label, true);
|
addItem(newLabel, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LabelFiltersList::showMenu(QPoint)
|
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;
|
++m_totalTorrents;
|
||||||
QString label = torrentItem->data(TorrentModelItem::TR_LABEL).toString();
|
QString label = torrent->label();
|
||||||
addItem(label, true);
|
addItem(label, true);
|
||||||
|
// FIXME: Drop this confusion.
|
||||||
// labelFilters->addItem() may have changed the label, update the model accordingly.
|
// 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;
|
--m_totalTorrents;
|
||||||
Q_ASSERT(torrentItem);
|
removeItem(torrent->label());
|
||||||
QString label = torrentItem->data(TorrentModelItem::TR_LABEL).toString();
|
|
||||||
removeItem(label);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LabelFiltersList::labelFromRow(int row) const
|
QString LabelFiltersList::labelFromRow(int row) const
|
||||||
@ -681,11 +685,10 @@ void TrackerFiltersList::applyFilter(int row)
|
|||||||
transferList->applyTrackerFilter(getHashes(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 = torrent->hash();
|
||||||
QString hash = handle->hash();
|
QList<BitTorrent::TrackerEntry> trackers = torrent->trackers();
|
||||||
QList<BitTorrent::TrackerEntry> trackers = handle->trackers();
|
|
||||||
foreach (const BitTorrent::TrackerEntry &tracker, trackers)
|
foreach (const BitTorrent::TrackerEntry &tracker, trackers)
|
||||||
addItem(tracker.url(), hash);
|
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));
|
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 = torrent->hash();
|
||||||
QString hash = handle->hash();
|
QList<BitTorrent::TrackerEntry> trackers = torrent->trackers();
|
||||||
QList<BitTorrent::TrackerEntry> trackers = handle->trackers();
|
|
||||||
foreach (const BitTorrent::TrackerEntry &tracker, trackers)
|
foreach (const BitTorrent::TrackerEntry &tracker, trackers)
|
||||||
removeItem(tracker.url(), hash);
|
removeItem(tracker.url(), hash);
|
||||||
|
|
||||||
|
@ -40,7 +40,6 @@ class QCheckBox;
|
|||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class TransferListWidget;
|
class TransferListWidget;
|
||||||
class TorrentModelItem;
|
|
||||||
|
|
||||||
namespace BitTorrent
|
namespace BitTorrent
|
||||||
{
|
{
|
||||||
@ -68,8 +67,8 @@ protected:
|
|||||||
private slots:
|
private slots:
|
||||||
virtual void showMenu(QPoint) = 0;
|
virtual void showMenu(QPoint) = 0;
|
||||||
virtual void applyFilter(int row) = 0;
|
virtual void applyFilter(int row) = 0;
|
||||||
virtual void handleNewTorrent(TorrentModelItem* torrentItem) = 0;
|
virtual void handleNewTorrent(BitTorrent::TorrentHandle *const) = 0;
|
||||||
virtual void torrentAboutToBeDeleted(TorrentModelItem* torrentItem) = 0;
|
virtual void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StatusFiltersWidget: public FiltersBase
|
class StatusFiltersWidget: public FiltersBase
|
||||||
@ -88,8 +87,8 @@ private:
|
|||||||
// No need to redeclare them here as slots.
|
// No need to redeclare them here as slots.
|
||||||
virtual void showMenu(QPoint);
|
virtual void showMenu(QPoint);
|
||||||
virtual void applyFilter(int row);
|
virtual void applyFilter(int row);
|
||||||
virtual void handleNewTorrent(TorrentModelItem*);
|
virtual void handleNewTorrent(BitTorrent::TorrentHandle *const);
|
||||||
virtual void torrentAboutToBeDeleted(TorrentModelItem*);
|
virtual void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const);
|
||||||
};
|
};
|
||||||
|
|
||||||
class LabelFiltersList: public FiltersBase
|
class LabelFiltersList: public FiltersBase
|
||||||
@ -106,7 +105,7 @@ private slots:
|
|||||||
void removeItem(const QString &label);
|
void removeItem(const QString &label);
|
||||||
void removeSelectedLabel();
|
void removeSelectedLabel();
|
||||||
void removeUnusedLabels();
|
void removeUnusedLabels();
|
||||||
void torrentChangedLabel(TorrentModelItem *torrentItem, QString old_label, QString new_label);
|
void torrentChangedLabel(BitTorrent::TorrentHandle *const torrent, const QString &oldLabel);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -114,8 +113,8 @@ private:
|
|||||||
// No need to redeclare them here as slots.
|
// No need to redeclare them here as slots.
|
||||||
virtual void showMenu(QPoint);
|
virtual void showMenu(QPoint);
|
||||||
virtual void applyFilter(int row);
|
virtual void applyFilter(int row);
|
||||||
virtual void handleNewTorrent(TorrentModelItem* torrentItem);
|
virtual void handleNewTorrent(BitTorrent::TorrentHandle *const torrent);
|
||||||
virtual void torrentAboutToBeDeleted(TorrentModelItem* torrentItem);
|
virtual void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const torrent);
|
||||||
QString labelFromRow(int row) const;
|
QString labelFromRow(int row) const;
|
||||||
int rowFromLabel(const QString &label) const;
|
int rowFromLabel(const QString &label) const;
|
||||||
|
|
||||||
@ -152,8 +151,8 @@ private:
|
|||||||
// No need to redeclare them here as slots.
|
// No need to redeclare them here as slots.
|
||||||
virtual void showMenu(QPoint);
|
virtual void showMenu(QPoint);
|
||||||
virtual void applyFilter(int row);
|
virtual void applyFilter(int row);
|
||||||
virtual void handleNewTorrent(TorrentModelItem* torrentItem);
|
virtual void handleNewTorrent(BitTorrent::TorrentHandle *const torrent);
|
||||||
virtual void torrentAboutToBeDeleted(TorrentModelItem* torrentItem);
|
virtual void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const torrent);
|
||||||
QString trackerFromRow(int row) const;
|
QString trackerFromRow(int row) const;
|
||||||
int rowFromTracker(const QString &tracker) const;
|
int rowFromTracker(const QString &tracker) const;
|
||||||
QString getHost(const QString &trakcer) const;
|
QString getHost(const QString &trakcer) const;
|
||||||
|
@ -75,7 +75,7 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
|
|||||||
{
|
{
|
||||||
const int column = sortColumn();
|
const int column = sortColumn();
|
||||||
|
|
||||||
if (column == TorrentModelItem::TR_NAME) {
|
if (column == TorrentModel::TR_NAME) {
|
||||||
QVariant vL = left.data();
|
QVariant vL = left.data();
|
||||||
QVariant vR = right.data();
|
QVariant vR = right.data();
|
||||||
if (!vL.isValid() || !vR.isValid() || (vL == vR))
|
if (!vL.isValid() || !vR.isValid() || (vL == vR))
|
||||||
@ -87,7 +87,7 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
|
|||||||
|
|
||||||
return QSortFilterProxyModel::lessThan(left, right);
|
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 vL = left.data().toDateTime();
|
||||||
QDateTime vR = right.data().toDateTime();
|
QDateTime vR = right.data().toDateTime();
|
||||||
|
|
||||||
@ -97,10 +97,10 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
|
|||||||
|
|
||||||
return vL < vR;
|
return vL < vR;
|
||||||
}
|
}
|
||||||
else if (column == TorrentModelItem::TR_PRIORITY) {
|
else if (column == TorrentModel::TR_PRIORITY) {
|
||||||
return lowerPositionThan(left, right);
|
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_active = left.data().toInt();
|
||||||
int left_total = left.data(Qt::UserRole).toInt();
|
int left_total = left.data(Qt::UserRole).toInt();
|
||||||
int right_active = right.data().toInt();
|
int right_active = right.data().toInt();
|
||||||
@ -116,10 +116,10 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
|
|||||||
return (left_active < right_active);
|
return (left_active < right_active);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (column == TorrentModelItem::TR_ETA) {
|
else if (column == TorrentModel::TR_ETA) {
|
||||||
TorrentModel *model = qobject_cast<TorrentModel *>(sourceModel());
|
TorrentModel *model = qobject_cast<TorrentModel *>(sourceModel());
|
||||||
const int prioL = model->data(model->index(left.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(), TorrentModelItem::TR_PRIORITY)).toInt();
|
const int prioR = model->data(model->index(right.row(), TorrentModel::TR_PRIORITY)).toInt();
|
||||||
const qlonglong etaL = left.data().toLongLong();
|
const qlonglong etaL = left.data().toLongLong();
|
||||||
const qlonglong etaR = right.data().toLongLong();
|
const qlonglong etaR = right.data().toLongLong();
|
||||||
const bool ascend = (sortOrder() == Qt::AscendingOrder);
|
const bool ascend = (sortOrder() == Qt::AscendingOrder);
|
||||||
@ -144,8 +144,8 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
|
|||||||
|
|
||||||
if (invalidL && invalidR) {
|
if (invalidL && invalidR) {
|
||||||
if (seedingL) { //Both seeding
|
if (seedingL) { //Both seeding
|
||||||
QDateTime dateL = model->data(model->index(left.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(), TorrentModelItem::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.
|
//not valid dates should be sorted at the bottom.
|
||||||
if (!dateL.isValid()) return false;
|
if (!dateL.isValid()) return false;
|
||||||
@ -164,7 +164,7 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
|
|||||||
return !invalidL;
|
return !invalidL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (column == TorrentModelItem::TR_LAST_ACTIVITY) {
|
else if (column == TorrentModel::TR_LAST_ACTIVITY) {
|
||||||
const qlonglong vL = left.data().toLongLong();
|
const qlonglong vL = left.data().toLongLong();
|
||||||
const qlonglong vR = right.data().toLongLong();
|
const qlonglong vR = right.data().toLongLong();
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
|
|||||||
|
|
||||||
return vL < vR;
|
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 vL = left.data().toDouble();
|
||||||
const qreal vR = right.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());
|
const TorrentModel *model = dynamic_cast<TorrentModel*>(sourceModel());
|
||||||
|
|
||||||
// Sort according to TR_PRIORITY
|
// Sort according to TR_PRIORITY
|
||||||
const int queueL = model->data(model->index(left.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(), TorrentModelItem::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)) {
|
||||||
if ((queueL > 0) && (queueR > 0))
|
if ((queueL > 0) && (queueR > 0))
|
||||||
return queueL < queueR;
|
return queueL < queueR;
|
||||||
@ -204,8 +204,8 @@ bool TransferListSortModel::lowerPositionThan(const QModelIndex &left, const QMo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sort according to TR_SEED_DATE
|
// Sort according to TR_SEED_DATE
|
||||||
const QDateTime dateL = model->data(model->index(left.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(), TorrentModelItem::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.isValid() && dateR.isValid()) {
|
||||||
if (dateL != dateR)
|
if (dateL != dateR)
|
||||||
return dateL < dateR;
|
return dateL < dateR;
|
||||||
@ -216,8 +216,8 @@ bool TransferListSortModel::lowerPositionThan(const QModelIndex &left, const QMo
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Finally, sort by hash
|
// Finally, sort by hash
|
||||||
const QString hashL(model->torrentHash(left.row()));
|
const QString hashL(model->torrentHandle(model->index(left.row()))->hash());
|
||||||
const QString hashR(model->torrentHash(right.row()));
|
const QString hashR(model->torrentHandle(model->index(right.row()))->hash());
|
||||||
return hashL < hashR;
|
return hashL < hashR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,8 @@
|
|||||||
#include "autoexpandabledialog.h"
|
#include "autoexpandabledialog.h"
|
||||||
#include "transferlistsortmodel.h"
|
#include "transferlistsortmodel.h"
|
||||||
|
|
||||||
|
static QStringList extractHashes(const QList<BitTorrent::TorrentHandle *> &torrents);
|
||||||
|
|
||||||
TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *main_window)
|
TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *main_window)
|
||||||
: QTreeView(parent)
|
: QTreeView(parent)
|
||||||
, main_window(main_window)
|
, main_window(main_window)
|
||||||
@ -80,7 +82,7 @@ TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *main_window)
|
|||||||
nameFilterModel = new TransferListSortModel();
|
nameFilterModel = new TransferListSortModel();
|
||||||
nameFilterModel->setDynamicSortFilter(true);
|
nameFilterModel->setDynamicSortFilter(true);
|
||||||
nameFilterModel->setSourceModel(listModel);
|
nameFilterModel->setSourceModel(listModel);
|
||||||
nameFilterModel->setFilterKeyColumn(TorrentModelItem::TR_NAME);
|
nameFilterModel->setFilterKeyColumn(TorrentModel::TR_NAME);
|
||||||
nameFilterModel->setFilterRole(Qt::DisplayRole);
|
nameFilterModel->setFilterRole(Qt::DisplayRole);
|
||||||
nameFilterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
nameFilterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
|
||||||
@ -101,40 +103,40 @@ TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *main_window)
|
|||||||
|
|
||||||
// Default hidden columns
|
// Default hidden columns
|
||||||
if (!column_loaded) {
|
if (!column_loaded) {
|
||||||
setColumnHidden(TorrentModelItem::TR_ADD_DATE, true);
|
setColumnHidden(TorrentModel::TR_ADD_DATE, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_SEED_DATE, true);
|
setColumnHidden(TorrentModel::TR_SEED_DATE, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_UPLIMIT, true);
|
setColumnHidden(TorrentModel::TR_UPLIMIT, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_DLLIMIT, true);
|
setColumnHidden(TorrentModel::TR_DLLIMIT, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_TRACKER, true);
|
setColumnHidden(TorrentModel::TR_TRACKER, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_AMOUNT_DOWNLOADED, true);
|
setColumnHidden(TorrentModel::TR_AMOUNT_DOWNLOADED, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_AMOUNT_UPLOADED, true);
|
setColumnHidden(TorrentModel::TR_AMOUNT_UPLOADED, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_AMOUNT_DOWNLOADED_SESSION, true);
|
setColumnHidden(TorrentModel::TR_AMOUNT_DOWNLOADED_SESSION, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_AMOUNT_UPLOADED_SESSION, true);
|
setColumnHidden(TorrentModel::TR_AMOUNT_UPLOADED_SESSION, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_AMOUNT_LEFT, true);
|
setColumnHidden(TorrentModel::TR_AMOUNT_LEFT, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_TIME_ELAPSED, true);
|
setColumnHidden(TorrentModel::TR_TIME_ELAPSED, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_SAVE_PATH, true);
|
setColumnHidden(TorrentModel::TR_SAVE_PATH, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_COMPLETED, true);
|
setColumnHidden(TorrentModel::TR_COMPLETED, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_RATIO_LIMIT, true);
|
setColumnHidden(TorrentModel::TR_RATIO_LIMIT, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_SEEN_COMPLETE_DATE, true);
|
setColumnHidden(TorrentModel::TR_SEEN_COMPLETE_DATE, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_LAST_ACTIVITY, true);
|
setColumnHidden(TorrentModel::TR_LAST_ACTIVITY, true);
|
||||||
setColumnHidden(TorrentModelItem::TR_TOTAL_SIZE, true);
|
setColumnHidden(TorrentModel::TR_TOTAL_SIZE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Ensure that at least one column is visible at all times
|
//Ensure that at least one column is visible at all times
|
||||||
bool atLeastOne = false;
|
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)) {
|
if (!isColumnHidden(i)) {
|
||||||
atLeastOne = true;
|
atLeastOne = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!atLeastOne)
|
if (!atLeastOne)
|
||||||
setColumnHidden(TorrentModelItem::TR_NAME, false);
|
setColumnHidden(TorrentModel::TR_NAME, false);
|
||||||
|
|
||||||
//When adding/removing columns between versions some may
|
//When adding/removing columns between versions some may
|
||||||
//end up being size 0 when the new version is launched with
|
//end up being size 0 when the new version is launched with
|
||||||
//a conf file from the previous version.
|
//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))
|
if (!columnWidth(i))
|
||||||
resizeColumnToContents(i);
|
resizeColumnToContents(i);
|
||||||
|
|
||||||
@ -177,16 +179,6 @@ void TransferListWidget::previewFile(QString filePath)
|
|||||||
openUrl(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
|
inline QModelIndex TransferListWidget::mapToSource(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
Q_ASSERT(index.isValid());
|
Q_ASSERT(index.isValid());
|
||||||
@ -204,9 +196,7 @@ inline QModelIndex TransferListWidget::mapFromSource(const QModelIndex &index) c
|
|||||||
|
|
||||||
void TransferListWidget::torrentDoubleClicked(const QModelIndex& index)
|
void TransferListWidget::torrentDoubleClicked(const QModelIndex& index)
|
||||||
{
|
{
|
||||||
const int row = mapToSource(index).row();
|
BitTorrent::TorrentHandle *const torrent = listModel->torrentHandle(mapToSource(index));
|
||||||
const QString hash = getHashFromRow(row);
|
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (!torrent) return;
|
if (!torrent) return;
|
||||||
|
|
||||||
int action;
|
int action;
|
||||||
@ -227,37 +217,30 @@ void TransferListWidget::torrentDoubleClicked(const QModelIndex& index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList TransferListWidget::getSelectedTorrentsHashes() const
|
QList<BitTorrent::TorrentHandle *> TransferListWidget::getSelectedTorrents() const
|
||||||
{
|
{
|
||||||
QStringList hashes;
|
QList<BitTorrent::TorrentHandle *> torrents;
|
||||||
const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
foreach (const QModelIndex &index, selectionModel()->selectedRows())
|
||||||
foreach (const QModelIndex &index, selectedIndexes)
|
torrents << listModel->torrentHandle(mapToSource(index));
|
||||||
hashes << getHashFromRow(mapToSource(index).row());
|
|
||||||
return hashes;
|
return torrents;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::setSelectedTorrentsLocation()
|
void TransferListWidget::setSelectedTorrentsLocation()
|
||||||
{
|
{
|
||||||
const QStringList hashes = getSelectedTorrentsHashes();
|
const QList<BitTorrent::TorrentHandle *> torrents = getSelectedTorrents();
|
||||||
if (hashes.isEmpty()) return;
|
if (torrents.isEmpty()) return;
|
||||||
|
|
||||||
BitTorrent::TorrentHandle *const firstTorrent = BitTorrent::Session::instance()->findTorrent(hashes.first());
|
|
||||||
if (!firstTorrent) return;
|
|
||||||
|
|
||||||
QString dir;
|
QString dir;
|
||||||
const QDir saveDir(firstTorrent->savePath());
|
const QDir saveDir(torrents[0]->savePath());
|
||||||
qDebug("Old save path is %s", qPrintable(saveDir.absolutePath()));
|
qDebug("Old save path is %s", qPrintable(saveDir.absolutePath()));
|
||||||
dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), saveDir.absolutePath(),
|
dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), saveDir.absolutePath(),
|
||||||
QFileDialog::DontConfirmOverwrite | QFileDialog::ShowDirsOnly | QFileDialog::HideNameFilterDetails);
|
QFileDialog::DontConfirmOverwrite | QFileDialog::ShowDirsOnly | QFileDialog::HideNameFilterDetails);
|
||||||
if (!dir.isNull()) {
|
if (!dir.isNull()) {
|
||||||
qDebug("New path is %s", qPrintable(dir));
|
qDebug("New path is %s", qPrintable(dir));
|
||||||
foreach (const QString &hash, hashes) {
|
foreach (BitTorrent::TorrentHandle *const torrent, torrents) {
|
||||||
// Actually move storage
|
// Actually move storage
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (!torrent) continue;
|
|
||||||
|
|
||||||
torrent->move(Utils::Fs::expandPathAbs(dir));
|
torrent->move(Utils::Fs::expandPathAbs(dir));
|
||||||
main_window->getProperties()->updateSavePath(torrent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,27 +259,20 @@ void TransferListWidget::resumeAllTorrents()
|
|||||||
|
|
||||||
void TransferListWidget::startSelectedTorrents()
|
void TransferListWidget::startSelectedTorrents()
|
||||||
{
|
{
|
||||||
foreach (const QString &hash, getSelectedTorrentsHashes()) {
|
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (torrent)
|
|
||||||
torrent->resume();
|
torrent->resume();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::forceStartSelectedTorrents()
|
void TransferListWidget::forceStartSelectedTorrents()
|
||||||
{
|
{
|
||||||
foreach (const QString &hash, getSelectedTorrentsHashes()) {
|
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (torrent)
|
|
||||||
torrent->resume(true);
|
torrent->resume(true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::startVisibleTorrents()
|
void TransferListWidget::startVisibleTorrents()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < nameFilterModel->rowCount(); ++i) {
|
for (int i = 0; i < nameFilterModel->rowCount(); ++i) {
|
||||||
const int row = mapToSource(nameFilterModel->index(i, 0)).row();
|
BitTorrent::TorrentHandle *const torrent = listModel->torrentHandle(mapToSource(nameFilterModel->index(i, 0)));
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(getHashFromRow(row));
|
|
||||||
if (torrent)
|
if (torrent)
|
||||||
torrent->resume();
|
torrent->resume();
|
||||||
}
|
}
|
||||||
@ -304,18 +280,14 @@ void TransferListWidget::startVisibleTorrents()
|
|||||||
|
|
||||||
void TransferListWidget::pauseSelectedTorrents()
|
void TransferListWidget::pauseSelectedTorrents()
|
||||||
{
|
{
|
||||||
foreach (const QString &hash, getSelectedTorrentsHashes()) {
|
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (torrent)
|
|
||||||
torrent->pause();
|
torrent->pause();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::pauseVisibleTorrents()
|
void TransferListWidget::pauseVisibleTorrents()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < nameFilterModel->rowCount(); ++i) {
|
for (int i = 0; i < nameFilterModel->rowCount(); ++i) {
|
||||||
const int row = mapToSource(nameFilterModel->index(i, 0)).row();
|
BitTorrent::TorrentHandle *const torrent = listModel->torrentHandle(mapToSource(nameFilterModel->index(i, 0)));
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(getHashFromRow(row));
|
|
||||||
if (torrent)
|
if (torrent)
|
||||||
torrent->pause();
|
torrent->pause();
|
||||||
}
|
}
|
||||||
@ -324,101 +296,90 @@ void TransferListWidget::pauseVisibleTorrents()
|
|||||||
void TransferListWidget::deleteSelectedTorrents()
|
void TransferListWidget::deleteSelectedTorrents()
|
||||||
{
|
{
|
||||||
if (main_window->getCurrentTabWidget() != this) return;
|
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;
|
bool delete_local_files = false;
|
||||||
if (Preferences::instance()->confirmTorrentDeletion() &&
|
if (Preferences::instance()->confirmTorrentDeletion() &&
|
||||||
!DeletionConfirmationDlg::askForDeletionConfirmation(delete_local_files, hashes.size(), torrent->name()))
|
!DeletionConfirmationDlg::askForDeletionConfirmation(delete_local_files, torrents.size(), torrents[0]->name()))
|
||||||
return;
|
return;
|
||||||
foreach (const QString &hash, hashes)
|
foreach (BitTorrent::TorrentHandle *const torrent, torrents)
|
||||||
BitTorrent::Session::instance()->deleteTorrent(hash, delete_local_files);
|
BitTorrent::Session::instance()->deleteTorrent(torrent->hash(), delete_local_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::deleteVisibleTorrents()
|
void TransferListWidget::deleteVisibleTorrents()
|
||||||
{
|
{
|
||||||
if (nameFilterModel->rowCount() <= 0) return;
|
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;
|
bool delete_local_files = false;
|
||||||
if (Preferences::instance()->confirmTorrentDeletion() &&
|
if (Preferences::instance()->confirmTorrentDeletion() &&
|
||||||
!DeletionConfirmationDlg::askForDeletionConfirmation(delete_local_files, hashes.size(), torrent->name()))
|
!DeletionConfirmationDlg::askForDeletionConfirmation(delete_local_files, torrents.size(), torrents[0]->name()))
|
||||||
return;
|
return;
|
||||||
foreach (const QString &hash, hashes)
|
foreach (BitTorrent::TorrentHandle *const torrent, torrents)
|
||||||
BitTorrent::Session::instance()->deleteTorrent(hash, delete_local_files);
|
BitTorrent::Session::instance()->deleteTorrent(torrent->hash(), delete_local_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::increasePrioSelectedTorrents()
|
void TransferListWidget::increasePrioSelectedTorrents()
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO;
|
||||||
if (main_window->getCurrentTabWidget() == this)
|
if (main_window->getCurrentTabWidget() == this)
|
||||||
BitTorrent::Session::instance()->increaseTorrentsPriority(getSelectedTorrentsHashes());
|
BitTorrent::Session::instance()->increaseTorrentsPriority(extractHashes(getSelectedTorrents()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::decreasePrioSelectedTorrents()
|
void TransferListWidget::decreasePrioSelectedTorrents()
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO;
|
||||||
if (main_window->getCurrentTabWidget() == this)
|
if (main_window->getCurrentTabWidget() == this)
|
||||||
BitTorrent::Session::instance()->decreaseTorrentsPriority(getSelectedTorrentsHashes());
|
BitTorrent::Session::instance()->decreaseTorrentsPriority(extractHashes(getSelectedTorrents()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::topPrioSelectedTorrents()
|
void TransferListWidget::topPrioSelectedTorrents()
|
||||||
{
|
{
|
||||||
if (main_window->getCurrentTabWidget() == this)
|
if (main_window->getCurrentTabWidget() == this)
|
||||||
BitTorrent::Session::instance()->topTorrentsPriority(getSelectedTorrentsHashes());
|
BitTorrent::Session::instance()->topTorrentsPriority(extractHashes(getSelectedTorrents()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::bottomPrioSelectedTorrents()
|
void TransferListWidget::bottomPrioSelectedTorrents()
|
||||||
{
|
{
|
||||||
if (main_window->getCurrentTabWidget() == this)
|
if (main_window->getCurrentTabWidget() == this)
|
||||||
BitTorrent::Session::instance()->bottomTorrentsPriority(getSelectedTorrentsHashes());
|
BitTorrent::Session::instance()->bottomTorrentsPriority(extractHashes(getSelectedTorrents()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::copySelectedMagnetURIs() const
|
void TransferListWidget::copySelectedMagnetURIs() const
|
||||||
{
|
{
|
||||||
QStringList magnet_uris;
|
QStringList magnet_uris;
|
||||||
const QStringList hashes = getSelectedTorrentsHashes();
|
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
|
||||||
foreach (const QString &hash, hashes) {
|
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (torrent)
|
|
||||||
magnet_uris << torrent->toMagnetUri();
|
magnet_uris << torrent->toMagnetUri();
|
||||||
}
|
|
||||||
qApp->clipboard()->setText(magnet_uris.join("\n"));
|
qApp->clipboard()->setText(magnet_uris.join("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::copySelectedNames() const
|
void TransferListWidget::copySelectedNames() const
|
||||||
{
|
{
|
||||||
QStringList torrent_names;
|
QStringList torrent_names;
|
||||||
const QStringList hashes = getSelectedTorrentsHashes();
|
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
|
||||||
foreach (const QString &hash, hashes) {
|
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (torrent)
|
|
||||||
torrent_names << torrent->name();
|
torrent_names << torrent->name();
|
||||||
}
|
|
||||||
qApp->clipboard()->setText(torrent_names.join("\n"));
|
qApp->clipboard()->setText(torrent_names.join("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::hidePriorityColumn(bool hide)
|
void TransferListWidget::hidePriorityColumn(bool hide)
|
||||||
{
|
{
|
||||||
qDebug("hidePriorityColumn(%d)", hide);
|
qDebug("hidePriorityColumn(%d)", hide);
|
||||||
setColumnHidden(TorrentModelItem::TR_PRIORITY, hide);
|
setColumnHidden(TorrentModel::TR_PRIORITY, hide);
|
||||||
if (!hide && !columnWidth(TorrentModelItem::TR_PRIORITY))
|
if (!hide && !columnWidth(TorrentModel::TR_PRIORITY))
|
||||||
resizeColumnToContents(TorrentModelItem::TR_PRIORITY);
|
resizeColumnToContents(TorrentModel::TR_PRIORITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::openSelectedTorrentsFolder() const
|
void TransferListWidget::openSelectedTorrentsFolder() const
|
||||||
{
|
{
|
||||||
QSet<QString> pathsList;
|
QSet<QString> pathsList;
|
||||||
const QStringList hashes = getSelectedTorrentsHashes();
|
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) {
|
||||||
foreach (const QString &hash, hashes) {
|
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (torrent) {
|
|
||||||
QString rootFolder = torrent->rootPath();
|
QString rootFolder = torrent->rootPath();
|
||||||
qDebug("Opening path at %s", qPrintable(rootFolder));
|
qDebug("Opening path at %s", qPrintable(rootFolder));
|
||||||
if (!pathsList.contains(rootFolder)) {
|
if (!pathsList.contains(rootFolder)) {
|
||||||
@ -426,15 +387,12 @@ void TransferListWidget::openSelectedTorrentsFolder() const
|
|||||||
openUrl(rootFolder);
|
openUrl(rootFolder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::previewSelectedTorrents()
|
void TransferListWidget::previewSelectedTorrents()
|
||||||
{
|
{
|
||||||
const QStringList hashes = getSelectedTorrentsHashes();
|
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) {
|
||||||
foreach (const QString &hash, hashes) {
|
if (torrent->hasMetadata())
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (torrent && torrent->hasMetadata())
|
|
||||||
new PreviewSelect(this, torrent);
|
new PreviewSelect(this, torrent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -444,19 +402,17 @@ void TransferListWidget::setDlLimitSelectedTorrents()
|
|||||||
QList<BitTorrent::TorrentHandle *> selected_torrents;
|
QList<BitTorrent::TorrentHandle *> selected_torrents;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
bool all_same_limit = true;
|
bool all_same_limit = true;
|
||||||
const QStringList hashes = getSelectedTorrentsHashes();
|
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) {
|
||||||
foreach (const QString &hash, hashes) {
|
if (!torrent->isSeed()) {
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (torrent && !torrent->isSeed()) {
|
|
||||||
selected_torrents << torrent;
|
selected_torrents << torrent;
|
||||||
// Determine current limit for selected torrents
|
// Determine current limit for selected torrents
|
||||||
if (first)
|
if (first)
|
||||||
first = false;
|
first = false;
|
||||||
else
|
else if (all_same_limit && (torrent->downloadLimit() != selected_torrents.first()->downloadLimit()))
|
||||||
if (all_same_limit && (torrent->downloadLimit() != selected_torrents.first()->downloadLimit()))
|
|
||||||
all_same_limit = false;
|
all_same_limit = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected_torrents.empty()) return;
|
if (selected_torrents.empty()) return;
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
@ -477,19 +433,15 @@ void TransferListWidget::setUpLimitSelectedTorrents()
|
|||||||
QList<BitTorrent::TorrentHandle *> selected_torrents;
|
QList<BitTorrent::TorrentHandle *> selected_torrents;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
bool all_same_limit = true;
|
bool all_same_limit = true;
|
||||||
const QStringList hashes = getSelectedTorrentsHashes();
|
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) {
|
||||||
foreach (const QString &hash, hashes) {
|
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (torrent) {
|
|
||||||
selected_torrents << torrent;
|
selected_torrents << torrent;
|
||||||
// Determine current limit for selected torrents
|
// Determine current limit for selected torrents
|
||||||
if (first)
|
if (first)
|
||||||
first = false;
|
first = false;
|
||||||
else
|
else if (all_same_limit && (torrent->uploadLimit() != selected_torrents.first()->uploadLimit()))
|
||||||
if (all_same_limit && (torrent->uploadLimit() != selected_torrents.first()->uploadLimit()))
|
|
||||||
all_same_limit = false;
|
all_same_limit = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (selected_torrents.empty()) return;
|
if (selected_torrents.empty()) return;
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
@ -507,27 +459,21 @@ void TransferListWidget::setUpLimitSelectedTorrents()
|
|||||||
|
|
||||||
void TransferListWidget::setMaxRatioSelectedTorrents()
|
void TransferListWidget::setMaxRatioSelectedTorrents()
|
||||||
{
|
{
|
||||||
const QStringList hashes = getSelectedTorrentsHashes();
|
const QList<BitTorrent::TorrentHandle *> torrents = getSelectedTorrents();
|
||||||
if (hashes.isEmpty())
|
if (torrents.isEmpty()) return;
|
||||||
return;
|
|
||||||
bool useGlobalValue = true;
|
bool useGlobalValue = true;
|
||||||
qreal currentMaxRatio = BitTorrent::Session::instance()->globalMaxRatio();;
|
qreal currentMaxRatio = BitTorrent::Session::instance()->globalMaxRatio();;
|
||||||
if (hashes.count() == 1) {
|
if (torrents.count() == 1)
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hashes.first());
|
currentMaxRatio = torrents[0]->maxRatio(&useGlobalValue);
|
||||||
if (torrent)
|
|
||||||
currentMaxRatio = torrent->maxRatio(&useGlobalValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpDownRatioDlg dlg(useGlobalValue, currentMaxRatio, BitTorrent::TorrentHandle::MAX_RATIO, this);
|
UpDownRatioDlg dlg(useGlobalValue, currentMaxRatio, BitTorrent::TorrentHandle::MAX_RATIO, this);
|
||||||
if (dlg.exec() != QDialog::Accepted) return;
|
if (dlg.exec() != QDialog::Accepted) return;
|
||||||
|
|
||||||
foreach (const QString &hash, hashes) {
|
foreach (BitTorrent::TorrentHandle *const torrent, torrents) {
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (torrent) {
|
|
||||||
qreal ratio = (dlg.useDefault() ? BitTorrent::TorrentHandle::USE_GLOBAL_RATIO : dlg.ratio());
|
qreal ratio = (dlg.useDefault() ? BitTorrent::TorrentHandle::USE_GLOBAL_RATIO : dlg.ratio());
|
||||||
torrent->setRatioLimit(ratio);
|
torrent->setRatioLimit(ratio);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::recheckSelectedTorrents()
|
void TransferListWidget::recheckSelectedTorrents()
|
||||||
@ -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);
|
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;
|
if (ret != QMessageBox::Yes) return;
|
||||||
|
|
||||||
const QStringList hashes = getSelectedTorrentsHashes();
|
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
|
||||||
foreach (const QString &hash, hashes) {
|
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (torrent)
|
|
||||||
torrent->forceRecheck();
|
torrent->forceRecheck();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// hide/show columns menu
|
// hide/show columns menu
|
||||||
@ -550,7 +492,7 @@ void TransferListWidget::displayDLHoSMenu(const QPoint&)
|
|||||||
hideshowColumn.setTitle(tr("Column visibility"));
|
hideshowColumn.setTitle(tr("Column visibility"));
|
||||||
QList<QAction*> actions;
|
QList<QAction*> actions;
|
||||||
for (int i = 0; i < listModel->columnCount(); ++i) {
|
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);
|
actions.append(0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -560,7 +502,7 @@ void TransferListWidget::displayDLHoSMenu(const QPoint&)
|
|||||||
actions.append(myAct);
|
actions.append(myAct);
|
||||||
}
|
}
|
||||||
int visibleCols = 0;
|
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))
|
if (!isColumnHidden(i))
|
||||||
visibleCols++;
|
visibleCols++;
|
||||||
|
|
||||||
@ -586,32 +528,22 @@ void TransferListWidget::displayDLHoSMenu(const QPoint&)
|
|||||||
|
|
||||||
void TransferListWidget::toggleSelectedTorrentsSuperSeeding() const
|
void TransferListWidget::toggleSelectedTorrentsSuperSeeding() const
|
||||||
{
|
{
|
||||||
const QStringList hashes = getSelectedTorrentsHashes();
|
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) {
|
||||||
foreach (const QString &hash, hashes) {
|
if (torrent->hasMetadata())
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (torrent && torrent->hasMetadata())
|
|
||||||
torrent->setSuperSeeding(!torrent->superSeeding());
|
torrent->setSuperSeeding(!torrent->superSeeding());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::toggleSelectedTorrentsSequentialDownload() const
|
void TransferListWidget::toggleSelectedTorrentsSequentialDownload() const
|
||||||
{
|
{
|
||||||
const QStringList hashes = getSelectedTorrentsHashes();
|
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
|
||||||
foreach (const QString &hash, hashes) {
|
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (torrent)
|
|
||||||
torrent->toggleSequentialDownload();
|
torrent->toggleSequentialDownload();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::toggleSelectedFirstLastPiecePrio() const
|
void TransferListWidget::toggleSelectedFirstLastPiecePrio() const
|
||||||
{
|
{
|
||||||
QStringList hashes = getSelectedTorrentsHashes();
|
foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents())
|
||||||
foreach (const QString &hash, hashes) {
|
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
|
||||||
if (torrent)
|
|
||||||
torrent->setFirstLastPiecePriority(!torrent->hasFirstLastPiecePriority());
|
torrent->setFirstLastPiecePriority(!torrent->hasFirstLastPiecePriority());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::askNewLabelForSelection()
|
void TransferListWidget::askNewLabelForSelection()
|
||||||
@ -649,9 +581,9 @@ void TransferListWidget::renameSelectedTorrent()
|
|||||||
const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
const QModelIndexList selectedIndexes = selectionModel()->selectedRows();
|
||||||
if (selectedIndexes.size() != 1) return;
|
if (selectedIndexes.size() != 1) return;
|
||||||
if (!selectedIndexes.first().isValid()) return;
|
if (!selectedIndexes.first().isValid()) return;
|
||||||
QModelIndex mi = listModel->index(mapToSource(selectedIndexes.first()).row(), TorrentModelItem::TR_NAME);
|
|
||||||
const QString hash = getHashFromRow(mi.row());
|
const QModelIndex mi = listModel->index(mapToSource(selectedIndexes.first()).row(), TorrentModel::TR_NAME);
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
BitTorrent::TorrentHandle *const torrent = listModel->torrentHandle(mi);
|
||||||
if (!torrent) return;
|
if (!torrent) return;
|
||||||
|
|
||||||
// Ask for a new Name
|
// Ask for a new Name
|
||||||
@ -666,19 +598,15 @@ void TransferListWidget::renameSelectedTorrent()
|
|||||||
|
|
||||||
void TransferListWidget::setSelectionLabel(QString label)
|
void TransferListWidget::setSelectionLabel(QString label)
|
||||||
{
|
{
|
||||||
const QStringList& hashes = getSelectedTorrentsHashes();
|
foreach (const QModelIndex &index, selectionModel()->selectedRows())
|
||||||
foreach (const QString &hash, hashes) {
|
listModel->setData(listModel->index(mapToSource(index).row(), TorrentModel::TR_LABEL), label, Qt::DisplayRole);
|
||||||
Q_ASSERT(!hash.isEmpty());
|
|
||||||
const int row = getRowFromHash(hash);
|
|
||||||
listModel->setData(listModel->index(row, TorrentModelItem::TR_LABEL), QVariant(label), Qt::DisplayRole);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListWidget::removeLabelFromRows(QString label)
|
void TransferListWidget::removeLabelFromRows(QString label)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < listModel->rowCount(); ++i) {
|
for (int i = 0; i < listModel->rowCount(); ++i) {
|
||||||
if (listModel->data(listModel->index(i, TorrentModelItem::TR_LABEL)) == label) {
|
if (listModel->data(listModel->index(i, TorrentModel::TR_LABEL)) == label) {
|
||||||
listModel->setData(listModel->index(i, TorrentModelItem::TR_LABEL), "", Qt::DisplayRole);
|
listModel->setData(listModel->index(i, TorrentModel::TR_LABEL), "", Qt::DisplayRole);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -750,9 +678,8 @@ void TransferListWidget::displayListMenu(const QPoint&)
|
|||||||
qDebug("Displaying menu");
|
qDebug("Displaying menu");
|
||||||
foreach (const QModelIndex &index, selectedIndexes) {
|
foreach (const QModelIndex &index, selectedIndexes) {
|
||||||
// Get the file name
|
// Get the file name
|
||||||
QString hash = getHashFromRow(mapToSource(index).row());
|
|
||||||
// Get handle and pause the torrent
|
// Get handle and pause the torrent
|
||||||
torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
torrent = listModel->torrentHandle(mapToSource(index));
|
||||||
if (!torrent) continue;
|
if (!torrent) continue;
|
||||||
|
|
||||||
if (torrent->hasMetadata())
|
if (torrent->hasMetadata())
|
||||||
@ -907,8 +834,7 @@ void TransferListWidget::currentChanged(const QModelIndex& current, const QModel
|
|||||||
qDebug("CURRENT CHANGED");
|
qDebug("CURRENT CHANGED");
|
||||||
BitTorrent::TorrentHandle *torrent = 0;
|
BitTorrent::TorrentHandle *torrent = 0;
|
||||||
if (current.isValid()) {
|
if (current.isValid()) {
|
||||||
const int row = mapToSource(current).row();
|
torrent = listModel->torrentHandle(mapToSource(current));
|
||||||
torrent = BitTorrent::Session::instance()->findTorrent(getHashFromRow(row));
|
|
||||||
// Scroll Fix
|
// Scroll Fix
|
||||||
scrollTo(current);
|
scrollTo(current);
|
||||||
}
|
}
|
||||||
@ -946,8 +872,8 @@ void TransferListWidget::applyStatusFilter(int f)
|
|||||||
nameFilterModel->setStatusFilter(static_cast<TorrentFilter::Type>(f));
|
nameFilterModel->setStatusFilter(static_cast<TorrentFilter::Type>(f));
|
||||||
// Select first item if nothing is selected
|
// Select first item if nothing is selected
|
||||||
if (selectionModel()->selectedRows(0).empty() && nameFilterModel->rowCount() > 0) {
|
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()));
|
qDebug("Nothing is selected, selecting first row: %s", qPrintable(nameFilterModel->index(0, TorrentModel::TR_NAME).data().toString()));
|
||||||
selectionModel()->setCurrentIndex(nameFilterModel->index(0, TorrentModelItem::TR_NAME), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
selectionModel()->setCurrentIndex(nameFilterModel->index(0, TorrentModel::TR_NAME), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -964,3 +890,11 @@ bool TransferListWidget::loadSettings()
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList extractHashes(const QList<BitTorrent::TorrentHandle *> &torrents)
|
||||||
|
{
|
||||||
|
QStringList hashes;
|
||||||
|
foreach (BitTorrent::TorrentHandle *const torrent, torrents)
|
||||||
|
hashes << torrent->hash();
|
||||||
|
|
||||||
|
return hashes;
|
||||||
|
}
|
||||||
|
@ -95,12 +95,10 @@ public slots:
|
|||||||
void renameSelectedTorrent();
|
void renameSelectedTorrent();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int getRowFromHash(QString hash) const;
|
|
||||||
QString getHashFromRow(int row) const;
|
|
||||||
QModelIndex mapToSource(const QModelIndex &index) const;
|
QModelIndex mapToSource(const QModelIndex &index) const;
|
||||||
QModelIndex mapFromSource(const QModelIndex &index) const;
|
QModelIndex mapFromSource(const QModelIndex &index) const;
|
||||||
bool loadSettings();
|
bool loadSettings();
|
||||||
QStringList getSelectedTorrentsHashes() const;
|
QList<BitTorrent::TorrentHandle *> getSelectedTorrents() const;
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void torrentDoubleClicked(const QModelIndex& index);
|
void torrentDoubleClicked(const QModelIndex& index);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user