mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-22 20:44:15 +00:00
Implement tracker list in the side panel. Closes #170.
This commit is contained in:
parent
36d2bee557
commit
f0d5ce4b98
@ -1278,6 +1278,7 @@ void QBtSession::loadTorrentTempData(QTorrentHandle &h, QString savePath, bool m
|
||||
|
||||
void QBtSession::mergeTorrents(QTorrentHandle& h_ex, const QString& magnet_uri)
|
||||
{
|
||||
QString hash = h_ex.hash();
|
||||
QList<QUrl> new_trackers = misc::magnetUriToTrackers(magnet_uri);
|
||||
bool trackers_added = false;
|
||||
foreach (const QUrl& new_tracker, new_trackers) {
|
||||
@ -1293,6 +1294,7 @@ void QBtSession::mergeTorrents(QTorrentHandle& h_ex, const QString& magnet_uri)
|
||||
if (!found) {
|
||||
h_ex.add_tracker(announce_entry(new_tracker.toString().toStdString()));
|
||||
trackers_added = true;
|
||||
emit trackerAdded(new_tracker.toString(), hash);
|
||||
}
|
||||
}
|
||||
if (trackers_added)
|
||||
@ -1302,6 +1304,7 @@ void QBtSession::mergeTorrents(QTorrentHandle& h_ex, const QString& magnet_uri)
|
||||
void QBtSession::mergeTorrents(QTorrentHandle &h_ex, boost::intrusive_ptr<torrent_info> t) {
|
||||
// Check if the torrent contains trackers or url seeds we don't know about
|
||||
// and add them
|
||||
QString hash = h_ex.hash();
|
||||
if (!h_ex.is_valid()) return;
|
||||
std::vector<announce_entry> existing_trackers = h_ex.trackers();
|
||||
std::vector<announce_entry> new_trackers = t->trackers();
|
||||
@ -1320,6 +1323,7 @@ void QBtSession::mergeTorrents(QTorrentHandle &h_ex, boost::intrusive_ptr<torren
|
||||
if (!found) {
|
||||
h_ex.add_tracker(announce_entry(new_tracker_url));
|
||||
trackers_added = true;
|
||||
emit trackerAdded(new_tracker_url.c_str(), hash);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,6 +288,7 @@ signals:
|
||||
void metadataReceivedHidden(const QTorrentHandle &h);
|
||||
void stateUpdate(const std::vector<libtorrent::torrent_status> &statuses);
|
||||
void statsReceived(const libtorrent::stats_alert&);
|
||||
void trackerAdded(const QString &tracker, const QString &hash);
|
||||
|
||||
private:
|
||||
// Bittorrent
|
||||
|
@ -312,6 +312,11 @@ QVariant TorrentModelItem::data(int column, int role) const
|
||||
}
|
||||
}
|
||||
|
||||
QTorrentHandle TorrentModelItem::torrentHandle() const
|
||||
{
|
||||
return m_torrent;
|
||||
}
|
||||
|
||||
// TORRENT MODEL
|
||||
|
||||
TorrentModel::TorrentModel(QObject *parent) :
|
||||
|
@ -59,6 +59,7 @@ public:
|
||||
bool setData(int column, const QVariant &value, int role = Qt::DisplayRole);
|
||||
inline QString const& hash() const { return m_hash; }
|
||||
State state() const;
|
||||
QTorrentHandle torrentHandle() const;
|
||||
|
||||
signals:
|
||||
void labelChanged(QString previous, QString current);
|
||||
|
@ -214,6 +214,9 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
connect(search_filter, SIGNAL(textChanged(QString)), transferList, SLOT(applyNameFilter(QString)));
|
||||
connect(hSplitter, SIGNAL(splitterMoved(int, int)), this, SLOT(writeSettings()));
|
||||
connect(vSplitter, SIGNAL(splitterMoved(int, int)), this, SLOT(writeSettings()));
|
||||
connect(properties, SIGNAL(trackerAdded(const QString&, const QString&)), transferListFilters, SLOT(addTracker(const QString&, const QString&)));
|
||||
connect(properties, SIGNAL(trackerRemoved(const QString&, const QString&)), transferListFilters, SLOT(removeTracker(const QString&, const QString&)));
|
||||
connect(QBtSession::instance(), SIGNAL(trackerAdded(const QString&, const QString&)), transferListFilters, SLOT(addTracker(const QString&, const QString&)));
|
||||
|
||||
vboxLayout->addWidget(tabs);
|
||||
|
||||
|
@ -111,6 +111,8 @@ PropertiesWidget::PropertiesWidget(QWidget *parent, MainWindow* main_window, Tra
|
||||
trackerList = new TrackerList(this);
|
||||
connect(trackerUpButton, SIGNAL(clicked()), trackerList, SLOT(moveSelectionUp()));
|
||||
connect(trackerDownButton, SIGNAL(clicked()), trackerList, SLOT(moveSelectionDown()));
|
||||
connect(trackerList, SIGNAL(trackerAdded(const QString&, const QString&)), this, SIGNAL(trackerAdded(const QString&, const QString&)));
|
||||
connect(trackerList, SIGNAL(trackerRemoved(const QString&, const QString&)), this, SIGNAL(trackerRemoved(const QString&, const QString&)));
|
||||
horizontalLayout_trackers->insertWidget(0, trackerList);
|
||||
connect(trackerList->header(), SIGNAL(sectionMoved(int, int, int)), trackerList, SLOT(saveSettings()));
|
||||
connect(trackerList->header(), SIGNAL(sectionResized(int, int, int)), trackerList, SLOT(saveSettings()));
|
||||
|
@ -69,6 +69,10 @@ public:
|
||||
PeerListWidget* getPeerList() const { return peersList; }
|
||||
QTreeView* getFilesList() const { return filesList; }
|
||||
|
||||
signals:
|
||||
void trackerAdded(const QString &tracker, const QString &hash);
|
||||
void trackerRemoved(const QString &tracker, const QString &hash);
|
||||
|
||||
protected:
|
||||
QPushButton* getButtonFromIndex(int index);
|
||||
bool applyPriorities();
|
||||
|
@ -300,14 +300,19 @@ void TrackerList::loadTrackers() {
|
||||
void TrackerList::askForTrackers() {
|
||||
QTorrentHandle h = properties->getCurrentTorrent();
|
||||
if (!h.is_valid()) return;
|
||||
QString hash = h.hash();
|
||||
QStringList trackers = TrackersAdditionDlg::askForTrackers(h);
|
||||
if (!trackers.empty()) {
|
||||
if (h.trackers().empty())
|
||||
emit trackerRemoved("", hash);
|
||||
|
||||
for (int i=0; i<trackers.count(); i++) {
|
||||
const QString& tracker = trackers[i];
|
||||
if (tracker.trimmed().isEmpty()) continue;
|
||||
announce_entry url(tracker.toStdString());
|
||||
url.tier = (topLevelItemCount() - NB_STICKY_ITEM) + i;
|
||||
h.add_tracker(url);
|
||||
emit trackerAdded(tracker, hash);
|
||||
}
|
||||
// Reannounce to new trackers
|
||||
if (!h.is_paused())
|
||||
@ -336,6 +341,7 @@ void TrackerList::deleteSelectedTrackers() {
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
QString hash = h.hash();
|
||||
QList<QTreeWidgetItem *> selected_items = getSelectedTrackerItems();
|
||||
if (selected_items.isEmpty()) return;
|
||||
QStringList urls_to_remove;
|
||||
@ -344,6 +350,7 @@ void TrackerList::deleteSelectedTrackers() {
|
||||
urls_to_remove << tracker_url;
|
||||
tracker_items.remove(tracker_url);
|
||||
delete item;
|
||||
emit trackerRemoved(tracker_url, hash);
|
||||
}
|
||||
// Iterate of trackers and remove selected ones
|
||||
std::vector<announce_entry> remaining_trackers;
|
||||
@ -357,6 +364,8 @@ void TrackerList::deleteSelectedTrackers() {
|
||||
}
|
||||
}
|
||||
h.replace_trackers(remaining_trackers);
|
||||
if (remaining_trackers.empty())
|
||||
emit trackerAdded("", hash);
|
||||
if (!h.is_paused())
|
||||
h.force_reannounce();
|
||||
// Reload Trackers
|
||||
@ -366,6 +375,7 @@ void TrackerList::deleteSelectedTrackers() {
|
||||
void TrackerList::editSelectedTracker() {
|
||||
try {
|
||||
QTorrentHandle h = properties->getCurrentTorrent();
|
||||
QString hash = h.hash();
|
||||
|
||||
QList<QTreeWidgetItem *> selected_items = getSelectedTrackerItems();
|
||||
if (selected_items.isEmpty())
|
||||
@ -402,6 +412,8 @@ void TrackerList::editSelectedTracker() {
|
||||
new_entry.tier = it->tier;
|
||||
match = true;
|
||||
*it = new_entry;
|
||||
emit trackerRemoved(tracker_url.toString(), hash);
|
||||
emit trackerAdded(new_tracker_url.toString(), hash);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,10 @@ public:
|
||||
TrackerList(PropertiesWidget *properties);
|
||||
~TrackerList();
|
||||
|
||||
signals:
|
||||
void trackerAdded(const QString &tracker, const QString &hash);
|
||||
void trackerRemoved(const QString &tracker, const QString &hash);
|
||||
|
||||
protected:
|
||||
QList<QTreeWidgetItem*> getSelectedTrackerItems() const;
|
||||
|
||||
|
@ -47,6 +47,9 @@
|
||||
#include "fs_utils.h"
|
||||
#include "autoexpandabledialog.h"
|
||||
#include "torrentfilterenum.h"
|
||||
#include "misc.h"
|
||||
#include "downloadthread.h"
|
||||
#include "logger.h"
|
||||
|
||||
LabelFiltersList::LabelFiltersList(QWidget *parent): QListWidget(parent)
|
||||
{
|
||||
@ -167,6 +170,215 @@ QSize StatusFiltersWidget::sizeHint() const
|
||||
return size;
|
||||
}
|
||||
|
||||
TrackerFiltersList::TrackerFiltersList(QWidget *parent): QListWidget(parent), m_downloader(new DownloadThread(this))
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
|
||||
setStyleSheet("QListWidget { background: transparent; border: 0 }");
|
||||
#if defined(Q_OS_MAC)
|
||||
setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
#endif
|
||||
QListWidgetItem *allTrackers = new QListWidgetItem(this);
|
||||
allTrackers->setData(Qt::DisplayRole, QVariant(tr("All trackers (0)")));
|
||||
allTrackers->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("network-server"));
|
||||
QListWidgetItem *noTracker = new QListWidgetItem(this);
|
||||
noTracker->setData(Qt::DisplayRole, QVariant(tr("Trackerless (0)")));
|
||||
noTracker->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("network-server"));
|
||||
m_trackers.insert("", QStringList());
|
||||
connect(m_downloader, SIGNAL(downloadFinished(QString, QString)), SLOT(handleFavicoDownload(QString, QString)));
|
||||
connect(m_downloader, SIGNAL(downloadFailure(QString, QString)), SLOT(handleFavicoFailure(QString, QString)));
|
||||
}
|
||||
|
||||
TrackerFiltersList::~TrackerFiltersList()
|
||||
{
|
||||
delete m_downloader;
|
||||
foreach (const QString &iconPath, m_iconPaths)
|
||||
fsutils::forceRemove(iconPath);
|
||||
}
|
||||
|
||||
void TrackerFiltersList::addItem(const QString &tracker, const QString &hash)
|
||||
{
|
||||
QStringList tmp;
|
||||
QListWidgetItem *trackerItem = 0;
|
||||
QString host = getHost(tracker);
|
||||
|
||||
if (m_trackers.contains(host)) {
|
||||
tmp = m_trackers.value(host);
|
||||
if (tmp.contains(hash))
|
||||
return;
|
||||
|
||||
if (host != "")
|
||||
trackerItem = item(rowFromTracker(host));
|
||||
else
|
||||
trackerItem = item(1);
|
||||
}
|
||||
else {
|
||||
trackerItem = new QListWidgetItem();
|
||||
trackerItem->setData(Qt::DecorationRole, IconProvider::instance()->getIcon("network-server"));
|
||||
m_downloader->downloadUrl(QString("http://") + host + QString("/favicon.ico"));
|
||||
}
|
||||
|
||||
tmp.append(hash);
|
||||
m_trackers.insert(host, tmp);
|
||||
if (host == "") {
|
||||
trackerItem->setText(tr("Trackerless (%1)").arg(tmp.size()));
|
||||
if (currentRow() == 1)
|
||||
emit currentRowChanged(1);
|
||||
return;
|
||||
}
|
||||
|
||||
trackerItem->setText(tr("%1 (%2)", "openbittorrent.com (10)").arg(host).arg(tmp.size()));
|
||||
|
||||
Q_ASSERT(count() >= 2);
|
||||
for (int i = 2; i<count(); ++i) {
|
||||
bool less = false;
|
||||
if (!(misc::naturalSort(host, item(i)->text(), less)))
|
||||
less = (host.localeAwareCompare(item(i)->text()) < 0);
|
||||
if (less) {
|
||||
insertItem(i, trackerItem);
|
||||
if (currentRow() == i)
|
||||
emit currentRowChanged(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
QListWidget::addItem(trackerItem);
|
||||
}
|
||||
|
||||
void TrackerFiltersList::addItem(const QTorrentHandle& handle)
|
||||
{
|
||||
QString hash = handle.hash();
|
||||
std::vector<libtorrent::announce_entry> trackers = handle.trackers();
|
||||
for (std::vector<libtorrent::announce_entry>::iterator i = trackers.begin(), e = trackers.end(); i != e; ++i)
|
||||
addItem(misc::toQString(i->url), hash);
|
||||
|
||||
//Check for trackerless torrent
|
||||
if (trackers.size() == 0)
|
||||
addItem("", hash);
|
||||
}
|
||||
|
||||
void TrackerFiltersList::removeItem(const QString &tracker, const QString &hash)
|
||||
{
|
||||
QString host = getHost(tracker);
|
||||
QListWidgetItem *trackerItem = 0;
|
||||
QStringList tmp = m_trackers.value(host);
|
||||
int row = 0;
|
||||
|
||||
if (tmp.empty())
|
||||
return;
|
||||
tmp.removeAll(hash);
|
||||
|
||||
if (host != "") {
|
||||
row = rowFromTracker(host);
|
||||
trackerItem = item(row);
|
||||
if (tmp.empty()) {
|
||||
if (currentRow() == row)
|
||||
setCurrentRow(0);
|
||||
delete trackerItem;
|
||||
m_trackers.remove(host);
|
||||
return;
|
||||
}
|
||||
trackerItem->setText(tr("%1 (%2)", "openbittorrent.com (10)").arg(host).arg(tmp.size()));
|
||||
}
|
||||
else {
|
||||
row = 1;
|
||||
trackerItem = item(1);
|
||||
trackerItem->setText(tr("Trackerless (%1)").arg(tmp.size()));
|
||||
}
|
||||
|
||||
m_trackers.insert(host, tmp);
|
||||
if (currentRow() == row)
|
||||
emit currentRowChanged(row);
|
||||
}
|
||||
|
||||
void TrackerFiltersList::removeItem(const QTorrentHandle& handle)
|
||||
{
|
||||
QString hash = handle.hash();
|
||||
std::vector<libtorrent::announce_entry> trackers = handle.trackers();
|
||||
for (std::vector<libtorrent::announce_entry>::iterator i = trackers.begin(), e = trackers.end(); i != e; ++i)
|
||||
removeItem(misc::toQString(i->url), hash);
|
||||
|
||||
//Check for trackerless torrent
|
||||
if (trackers.size() == 0)
|
||||
removeItem("", hash);
|
||||
}
|
||||
|
||||
void TrackerFiltersList::setTorrentCount(int all)
|
||||
{
|
||||
item(0)->setText(tr("All trackers (%1)").arg(all));
|
||||
}
|
||||
|
||||
QStringList TrackerFiltersList::getHashes(int row)
|
||||
{
|
||||
if (row == 1)
|
||||
return m_trackers.value("");
|
||||
else
|
||||
return m_trackers.value(trackerFromRow(row));
|
||||
}
|
||||
|
||||
void TrackerFiltersList::handleFavicoDownload(const QString& url, const QString& filePath)
|
||||
{
|
||||
QString host = getHost(url);
|
||||
if (!m_trackers.contains(host))
|
||||
return;
|
||||
|
||||
QListWidgetItem *trackerItem = item(rowFromTracker(host));
|
||||
QIcon icon(filePath);
|
||||
//Detect a non-decodable icon
|
||||
bool invalid = icon.pixmap(icon.availableSizes().first()).isNull();
|
||||
if (invalid) {
|
||||
if (url.endsWith(".ico", Qt::CaseInsensitive)) {
|
||||
Logger::instance()->addMessage(tr("Couldn't decode favico for url `%1`. Trying to download favico in PNG format.").arg(url),
|
||||
Log::WARNING);
|
||||
m_downloader->downloadUrl(url.left(url.size() - 4) + ".png");
|
||||
}
|
||||
else {
|
||||
Logger::instance()->addMessage(tr("Couldn't decode favico for url `%1`.").arg(url), Log::WARNING);
|
||||
}
|
||||
fsutils::forceRemove(filePath);
|
||||
}
|
||||
else {
|
||||
trackerItem->setData(Qt::DecorationRole, QVariant(QIcon(filePath)));
|
||||
m_iconPaths.append(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
void TrackerFiltersList::handleFavicoFailure(const QString& url, const QString& error)
|
||||
{
|
||||
// Don't use getHost() on the url here. Print the full url. The error might relate to
|
||||
// that.
|
||||
Logger::instance()->addMessage(tr("Couldn't download favico for url `%1`. Reason: `%2`").arg(url).arg(error),
|
||||
Log::WARNING);
|
||||
}
|
||||
|
||||
QString TrackerFiltersList::trackerFromRow(int row) const
|
||||
{
|
||||
Q_ASSERT(row > 1);
|
||||
const QString &tracker = item(row)->text();
|
||||
QStringList parts = tracker.split(" ");
|
||||
Q_ASSERT(parts.size() >= 2);
|
||||
parts.removeLast(); // Remove trailing number
|
||||
return parts.join(" ");
|
||||
}
|
||||
|
||||
int TrackerFiltersList::rowFromTracker(const QString &tracker) const
|
||||
{
|
||||
Q_ASSERT(!tracker.isEmpty());
|
||||
for (int i = 2; i<count(); ++i)
|
||||
if (tracker == trackerFromRow(i)) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
QString TrackerFiltersList::getHost(const QString &trakcer) const
|
||||
{
|
||||
QUrl url(trakcer);
|
||||
QString longHost = url.host();
|
||||
QString tld = url.topLevelDomain();
|
||||
// We want the domain + tld. Subdomains should be disregarded
|
||||
int index = longHost.lastIndexOf('.', -(tld.size() + 1));
|
||||
if (index == -1)
|
||||
return longHost;
|
||||
return longHost.mid(index + 1);
|
||||
}
|
||||
|
||||
TransferListFiltersWidget::TransferListFiltersWidget(QWidget *parent, TransferListWidget *transferList): QFrame(parent), transferList(transferList), nb_labeled(0), nb_torrents(0)
|
||||
{
|
||||
// Construct lists
|
||||
@ -187,8 +399,15 @@ TransferListFiltersWidget::TransferListFiltersWidget(QWidget *parent, TransferLi
|
||||
vLayout->addWidget(labelsLabel);
|
||||
labelFilters = new LabelFiltersList(this);
|
||||
vLayout->addWidget(labelFilters);
|
||||
QLabel *trackersLabel = new QLabel(tr("Trackers"));
|
||||
trackersLabel->setIndent(2);
|
||||
trackersLabel->setFont(font);
|
||||
vLayout->addWidget(trackersLabel);
|
||||
trackerFilters = new TrackerFiltersList(this);
|
||||
vLayout->addWidget(trackerFilters);
|
||||
setLayout(vLayout);
|
||||
labelFilters->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
trackerFilters->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
statusFilters->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
statusFilters->setSpacing(0);
|
||||
setContentsMargins(0,0,0,0);
|
||||
@ -222,6 +441,7 @@ TransferListFiltersWidget::TransferListFiltersWidget(QWidget *parent, TransferLi
|
||||
connect(transferList->getSourceModel(), SIGNAL(torrentAdded(TorrentModelItem*)), SLOT(handleNewTorrent(TorrentModelItem*)));
|
||||
connect(labelFilters, SIGNAL(currentRowChanged(int)), this, SLOT(applyLabelFilter(int)));
|
||||
connect(labelFilters, SIGNAL(torrentDropped(int)), this, SLOT(torrentDropped(int)));
|
||||
connect(trackerFilters, SIGNAL(currentRowChanged(int)), this, SLOT(applyTrackerFilter(int)));
|
||||
connect(transferList->getSourceModel(), SIGNAL(torrentAboutToBeRemoved(TorrentModelItem*)), SLOT(torrentAboutToBeDeleted(TorrentModelItem*)));
|
||||
connect(transferList->getSourceModel(), SIGNAL(torrentChangedLabel(TorrentModelItem*,QString,QString)), SLOT(torrentChangedLabel(TorrentModelItem*, QString, QString)));
|
||||
|
||||
@ -237,11 +457,16 @@ TransferListFiltersWidget::TransferListFiltersWidget(QWidget *parent, TransferLi
|
||||
loadSettings();
|
||||
|
||||
labelFilters->setCurrentRow(0);
|
||||
trackerFilters->setCurrentRow(0);
|
||||
//labelFilters->selectionModel()->select(labelFilters->model()->index(0,0), QItemSelectionModel::Select);
|
||||
|
||||
// Label menu
|
||||
labelFilters->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(labelFilters, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showLabelMenu(QPoint)));
|
||||
|
||||
// Tracker menu
|
||||
trackerFilters->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(trackerFilters, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showTrackerMenu(QPoint)));
|
||||
}
|
||||
|
||||
TransferListFiltersWidget::~TransferListFiltersWidget()
|
||||
@ -249,6 +474,7 @@ TransferListFiltersWidget::~TransferListFiltersWidget()
|
||||
saveSettings();
|
||||
delete statusFilters;
|
||||
delete labelFilters;
|
||||
delete trackerFilters;
|
||||
delete vLayout;
|
||||
}
|
||||
|
||||
@ -311,6 +537,16 @@ void TransferListFiltersWidget::addLabel(QString& label)
|
||||
Preferences::instance()->addTorrentLabel(label);
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::addTracker(const QString &tracker, const QString &hash)
|
||||
{
|
||||
trackerFilters->addItem(tracker, hash);
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::removeTracker(const QString &tracker, const QString &hash)
|
||||
{
|
||||
trackerFilters->removeItem(tracker, hash);
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::showLabelMenu(QPoint)
|
||||
{
|
||||
QMenu labelMenu(labelFilters);
|
||||
@ -370,6 +606,25 @@ void TransferListFiltersWidget::showLabelMenu(QPoint)
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::showTrackerMenu(QPoint)
|
||||
{
|
||||
QMenu trackerMenu(trackerFilters);
|
||||
QAction *startAct = trackerMenu.addAction(IconProvider::instance()->getIcon("media-playback-start"), tr("Resume torrents"));
|
||||
QAction *pauseAct = trackerMenu.addAction(IconProvider::instance()->getIcon("media-playback-pause"), tr("Pause torrents"));
|
||||
QAction *deleteTorrentsAct = trackerMenu.addAction(IconProvider::instance()->getIcon("edit-delete"), tr("Delete torrents"));
|
||||
QAction *act = 0;
|
||||
act = trackerMenu.exec(QCursor::pos());
|
||||
|
||||
if (act) {
|
||||
if (act == startAct)
|
||||
transferList->startVisibleTorrents();
|
||||
else if (act == pauseAct)
|
||||
transferList->pauseVisibleTorrents();
|
||||
else if (act == deleteTorrentsAct)
|
||||
transferList->deleteVisibleTorrents();
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::removeSelectedLabel()
|
||||
{
|
||||
const int row = labelFilters->row(labelFilters->selectedItems().first());
|
||||
@ -416,6 +671,14 @@ void TransferListFiltersWidget::applyLabelFilter(int row)
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::applyTrackerFilter(int row)
|
||||
{
|
||||
if (row == 0)
|
||||
transferList->applyTrackerFilterAll();
|
||||
else
|
||||
transferList->applyTrackerFilter(trackerFilters->getHashes(row));
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::torrentChangedLabel(TorrentModelItem *torrentItem, QString old_label, QString new_label)
|
||||
{
|
||||
Q_UNUSED(torrentItem);
|
||||
@ -471,6 +734,8 @@ void TransferListFiltersWidget::handleNewTorrent(TorrentModelItem* torrentItem)
|
||||
Q_ASSERT(nb_labeled >= 0);
|
||||
Q_ASSERT(nb_labeled <= nb_torrents);
|
||||
updateStickyLabelCounters();
|
||||
trackerFilters->addItem(torrentItem->torrentHandle());
|
||||
trackerFilters->setTorrentCount(nb_torrents);
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::torrentAboutToBeDeleted(TorrentModelItem* torrentItem)
|
||||
@ -492,6 +757,8 @@ void TransferListFiltersWidget::torrentAboutToBeDeleted(TorrentModelItem* torren
|
||||
Q_ASSERT(nb_labeled >= 0);
|
||||
Q_ASSERT(nb_labeled <= nb_torrents);
|
||||
updateStickyLabelCounters();
|
||||
trackerFilters->removeItem(torrentItem->torrentHandle());
|
||||
trackerFilters->setTorrentCount(nb_torrents);
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::updateStickyLabelCounters()
|
||||
|
@ -42,6 +42,8 @@ QT_END_NAMESPACE
|
||||
|
||||
class TransferListWidget;
|
||||
class TorrentModelItem;
|
||||
class QTorrentHandle;
|
||||
class DownloadThread;
|
||||
|
||||
class LabelFiltersList: public QListWidget
|
||||
{
|
||||
@ -83,6 +85,35 @@ private:
|
||||
bool m_shown;
|
||||
};
|
||||
|
||||
class TrackerFiltersList: public QListWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TrackerFiltersList(QWidget *parent);
|
||||
~TrackerFiltersList();
|
||||
|
||||
// Redefine addItem() to make sure the list stays sorted
|
||||
void addItem(const QString &tracker, const QString &hash);
|
||||
void addItem(const QTorrentHandle &handle);
|
||||
void removeItem(const QString &tracker, const QString &hash);
|
||||
void removeItem(const QTorrentHandle &handle);
|
||||
void setTorrentCount(int all);
|
||||
QStringList getHashes(int row);
|
||||
|
||||
public slots:
|
||||
void handleFavicoDownload(const QString &url, const QString &filePath);
|
||||
void handleFavicoFailure(const QString &url, const QString &reason);
|
||||
|
||||
private:
|
||||
QHash<QString, QStringList> m_trackers;
|
||||
QString trackerFromRow(int row) const;
|
||||
int rowFromTracker(const QString &tracker) const;
|
||||
QString getHost(const QString &trakcer) const;
|
||||
DownloadThread *m_downloader;
|
||||
QStringList m_iconPaths;
|
||||
};
|
||||
|
||||
class TransferListFiltersWidget: public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -91,6 +122,7 @@ private:
|
||||
QHash<QString, int> customLabels;
|
||||
StatusFiltersWidget* statusFilters;
|
||||
LabelFiltersList* labelFilters;
|
||||
TrackerFiltersList* trackerFilters;
|
||||
QVBoxLayout* vLayout;
|
||||
TransferListWidget *transferList;
|
||||
int nb_labeled;
|
||||
@ -105,14 +137,20 @@ public:
|
||||
void saveSettings() const;
|
||||
void loadSettings();
|
||||
|
||||
public slots:
|
||||
void addTracker(const QString &tracker, const QString &hash);
|
||||
void removeTracker(const QString &tracker, const QString &hash);
|
||||
|
||||
protected slots:
|
||||
void updateTorrentNumbers();
|
||||
void torrentDropped(int row);
|
||||
void addLabel(QString& label);
|
||||
void showLabelMenu(QPoint);
|
||||
void showTrackerMenu(QPoint);
|
||||
void removeSelectedLabel();
|
||||
void removeUnusedLabels();
|
||||
void applyLabelFilter(int row);
|
||||
void applyTrackerFilter(int row);
|
||||
void torrentChangedLabel(TorrentModelItem *torrentItem, QString old_label, QString new_label);
|
||||
void handleNewTorrent(TorrentModelItem* torrentItem);
|
||||
void torrentAboutToBeDeleted(TorrentModelItem* torrentItem);
|
||||
|
@ -36,6 +36,8 @@
|
||||
TransferListSortModel::TransferListSortModel(QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
, filter0(TorrentFilter::ALL)
|
||||
, labelFilterEnabled(false)
|
||||
, trackerFilterEnabled(false)
|
||||
{}
|
||||
|
||||
void TransferListSortModel::setStatusFilter(const TorrentFilter::TorrentFilter &filter) {
|
||||
@ -45,7 +47,7 @@ void TransferListSortModel::setStatusFilter(const TorrentFilter::TorrentFilter &
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListSortModel::setLabelFilter(QString const& label) {
|
||||
void TransferListSortModel::setLabelFilter(const QString &label) {
|
||||
if (!labelFilterEnabled || labelFilter != label) {
|
||||
labelFilterEnabled = true;
|
||||
labelFilter = label;
|
||||
@ -61,6 +63,22 @@ void TransferListSortModel::disableLabelFilter() {
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListSortModel::setTrackerFilter(const QStringList &hashes) {
|
||||
if (!trackerFilterEnabled || trackerFilter != hashes) {
|
||||
trackerFilterEnabled = true;
|
||||
trackerFilter = hashes;
|
||||
invalidateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
void TransferListSortModel::disableTrackerFilter() {
|
||||
if (trackerFilterEnabled) {
|
||||
trackerFilterEnabled = false;
|
||||
trackerFilter = QStringList();
|
||||
invalidateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex &right) const {
|
||||
const int column = sortColumn();
|
||||
|
||||
@ -197,6 +215,7 @@ bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex
|
||||
bool TransferListSortModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
||||
return matchStatusFilter(sourceRow, sourceParent)
|
||||
&& matchLabelFilter(sourceRow, sourceParent)
|
||||
&& matchTrackerFilter(sourceRow, sourceParent)
|
||||
&& QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
|
||||
}
|
||||
|
||||
@ -258,3 +277,14 @@ bool TransferListSortModel::matchLabelFilter(int sourceRow, const QModelIndex &s
|
||||
|
||||
return model->index(sourceRow, TorrentModelItem::TR_LABEL, sourceParent).data().toString() == labelFilter;
|
||||
}
|
||||
|
||||
bool TransferListSortModel::matchTrackerFilter(int sourceRow, const QModelIndex &sourceParent) const {
|
||||
if (!trackerFilterEnabled)
|
||||
return true;
|
||||
|
||||
TorrentModel *model = qobject_cast<TorrentModel *>(sourceModel());
|
||||
if (!model)
|
||||
return false;
|
||||
|
||||
return trackerFilter.contains(model->torrentHash(sourceRow));
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#define TRANSFERLISTSORTMODEL_H
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStringList>
|
||||
#include "torrentfilterenum.h"
|
||||
|
||||
class TransferListSortModel : public QSortFilterProxyModel {
|
||||
@ -41,8 +42,10 @@ public:
|
||||
TransferListSortModel(QObject *parent = 0);
|
||||
|
||||
void setStatusFilter(const TorrentFilter::TorrentFilter &filter);
|
||||
void setLabelFilter(QString const& label);
|
||||
void setLabelFilter(const QString &label);
|
||||
void disableLabelFilter();
|
||||
void setTrackerFilter(const QStringList &hashes);
|
||||
void disableTrackerFilter();
|
||||
|
||||
private:
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
|
||||
@ -50,12 +53,15 @@ private:
|
||||
|
||||
bool matchStatusFilter(int sourceRow, const QModelIndex &sourceParent) const;
|
||||
bool matchLabelFilter(int sourceRow, const QModelIndex &sourceParent) const;
|
||||
bool matchTrackerFilter(int sourceRow, const QModelIndex &sourceParent) const;
|
||||
|
||||
private:
|
||||
TorrentFilter::TorrentFilter filter0;
|
||||
|
||||
bool labelFilterEnabled;
|
||||
QString labelFilter;
|
||||
bool trackerFilterEnabled;
|
||||
QStringList trackerFilter;
|
||||
};
|
||||
|
||||
#endif // TRANSFERLISTSORTMODEL_H
|
||||
|
@ -938,6 +938,16 @@ void TransferListWidget::applyLabelFilter(QString label)
|
||||
nameFilterModel->setLabelFilter(label);
|
||||
}
|
||||
|
||||
void TransferListWidget::applyTrackerFilterAll()
|
||||
{
|
||||
nameFilterModel->disableTrackerFilter();
|
||||
}
|
||||
|
||||
void TransferListWidget::applyTrackerFilter(const QStringList &hashes)
|
||||
{
|
||||
nameFilterModel->setTrackerFilter(hashes);
|
||||
}
|
||||
|
||||
void TransferListWidget::applyNameFilter(const QString& name)
|
||||
{
|
||||
nameFilterModel->setFilterRegExp(QRegExp(QRegExp::escape(name), Qt::CaseInsensitive));
|
||||
|
@ -84,6 +84,8 @@ public slots:
|
||||
void applyStatusFilter(int f);
|
||||
void applyLabelFilterAll();
|
||||
void applyLabelFilter(QString label);
|
||||
void applyTrackerFilterAll();
|
||||
void applyTrackerFilter(const QStringList &hashes);
|
||||
void previewFile(QString filePath);
|
||||
void removeLabelFromRows(QString label);
|
||||
void renameSelectedTorrent();
|
||||
|
Loading…
x
Reference in New Issue
Block a user