Browse Source

Merge pull request #13912 from Chocobo1/infohash

Use the correct type when referring to info hash
adaptive-webui-19844
Mike Tzou 4 years ago committed by GitHub
parent
commit
d484c0e7ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      src/base/bittorrent/infohash.cpp
  2. 4
      src/base/bittorrent/infohash.h
  3. 13
      src/base/torrentfilter.cpp
  4. 18
      src/base/torrentfilter.h
  5. 6
      src/gui/mainwindow.cpp
  6. 194
      src/gui/transferlistfilterswidget.cpp
  7. 44
      src/gui/transferlistfilterswidget.h
  8. 5
      src/gui/transferlistsortmodel.cpp
  9. 7
      src/gui/transferlistsortmodel.h
  10. 3
      src/gui/transferlistwidget.cpp
  11. 5
      src/gui/transferlistwidget.h
  12. 8
      src/webui/api/torrentscontroller.cpp

5
src/base/bittorrent/infohash.cpp

@ -35,11 +35,6 @@ using namespace BitTorrent;
const int InfoHashTypeId = qRegisterMetaType<InfoHash>(); const int InfoHashTypeId = qRegisterMetaType<InfoHash>();
InfoHash::InfoHash()
: m_valid(false)
{
}
InfoHash::InfoHash(const lt::sha1_hash &nativeHash) InfoHash::InfoHash(const lt::sha1_hash &nativeHash)
: m_valid(true) : m_valid(true)
, m_nativeHash(nativeHash) , m_nativeHash(nativeHash)

4
src/base/bittorrent/infohash.h

@ -38,7 +38,7 @@ namespace BitTorrent
class InfoHash class InfoHash
{ {
public: public:
InfoHash(); InfoHash() = default;
InfoHash(const lt::sha1_hash &nativeHash); InfoHash(const lt::sha1_hash &nativeHash);
InfoHash(const QString &hashString); InfoHash(const QString &hashString);
InfoHash(const InfoHash &other) = default; InfoHash(const InfoHash &other) = default;
@ -54,7 +54,7 @@ namespace BitTorrent
operator QString() const; operator QString() const;
private: private:
bool m_valid; bool m_valid = false;
lt::sha1_hash m_nativeHash; lt::sha1_hash m_nativeHash;
QString m_hashString; QString m_hashString;
}; };

13
src/base/torrentfilter.cpp

@ -32,7 +32,7 @@
#include "bittorrent/torrenthandle.h" #include "bittorrent/torrenthandle.h"
const QString TorrentFilter::AnyCategory; const QString TorrentFilter::AnyCategory;
const QStringSet TorrentFilter::AnyHash = (QStringSet() << QString()); const InfoHashSet TorrentFilter::AnyHash {{}};
const QString TorrentFilter::AnyTag; const QString TorrentFilter::AnyTag;
const TorrentFilter TorrentFilter::DownloadingTorrent(TorrentFilter::Downloading); const TorrentFilter TorrentFilter::DownloadingTorrent(TorrentFilter::Downloading);
@ -49,12 +49,7 @@ const TorrentFilter TorrentFilter::ErroredTorrent(TorrentFilter::Errored);
using BitTorrent::TorrentHandle; using BitTorrent::TorrentHandle;
TorrentFilter::TorrentFilter() TorrentFilter::TorrentFilter(const Type type, const InfoHashSet &hashSet, const QString &category, const QString &tag)
: m_type(All)
{
}
TorrentFilter::TorrentFilter(const Type type, const QStringSet &hashSet, const QString &category, const QString &tag)
: m_type(type) : m_type(type)
, m_category(category) , m_category(category)
, m_tag(tag) , m_tag(tag)
@ -62,7 +57,7 @@ TorrentFilter::TorrentFilter(const Type type, const QStringSet &hashSet, const Q
{ {
} }
TorrentFilter::TorrentFilter(const QString &filter, const QStringSet &hashSet, const QString &category, const QString &tag) TorrentFilter::TorrentFilter(const QString &filter, const InfoHashSet &hashSet, const QString &category, const QString &tag)
: m_type(All) : m_type(All)
, m_category(category) , m_category(category)
, m_tag(tag) , m_tag(tag)
@ -112,7 +107,7 @@ bool TorrentFilter::setTypeByName(const QString &filter)
return setType(type); return setType(type);
} }
bool TorrentFilter::setHashSet(const QStringSet &hashSet) bool TorrentFilter::setHashSet(const InfoHashSet &hashSet)
{ {
if (m_hashSet != hashSet) if (m_hashSet != hashSet)
{ {

18
src/base/torrentfilter.h

@ -32,13 +32,15 @@
#include <QSet> #include <QSet>
#include <QString> #include <QString>
typedef QSet<QString> QStringSet; #include "base/bittorrent/infohash.h"
namespace BitTorrent namespace BitTorrent
{ {
class TorrentHandle; class TorrentHandle;
} }
using InfoHashSet = QSet<BitTorrent::InfoHash>;
class TorrentFilter class TorrentFilter
{ {
public: public:
@ -60,7 +62,7 @@ public:
// These mean any permutation, including no category / tag. // These mean any permutation, including no category / tag.
static const QString AnyCategory; static const QString AnyCategory;
static const QStringSet AnyHash; static const InfoHashSet AnyHash;
static const QString AnyTag; static const QString AnyTag;
static const TorrentFilter DownloadingTorrent; static const TorrentFilter DownloadingTorrent;
@ -75,15 +77,15 @@ public:
static const TorrentFilter StalledDownloadingTorrent; static const TorrentFilter StalledDownloadingTorrent;
static const TorrentFilter ErroredTorrent; static const TorrentFilter ErroredTorrent;
TorrentFilter(); TorrentFilter() = default;
// category & tags: pass empty string for uncategorized / untagged torrents. // category & tags: pass empty string for uncategorized / untagged torrents.
// Pass null string (QString()) to disable filtering (i.e. all torrents). // Pass null string (QString()) to disable filtering (i.e. all torrents).
TorrentFilter(Type type, const QStringSet &hashSet = AnyHash, const QString &category = AnyCategory, const QString &tag = AnyTag); TorrentFilter(Type type, const InfoHashSet &hashSet = AnyHash, const QString &category = AnyCategory, const QString &tag = AnyTag);
TorrentFilter(const QString &filter, const QStringSet &hashSet = AnyHash, const QString &category = AnyCategory, const QString &tags = AnyTag); TorrentFilter(const QString &filter, const InfoHashSet &hashSet = AnyHash, const QString &category = AnyCategory, const QString &tags = AnyTag);
bool setType(Type type); bool setType(Type type);
bool setTypeByName(const QString &filter); bool setTypeByName(const QString &filter);
bool setHashSet(const QStringSet &hashSet); bool setHashSet(const InfoHashSet &hashSet);
bool setCategory(const QString &category); bool setCategory(const QString &category);
bool setTag(const QString &tag); bool setTag(const QString &tag);
@ -95,10 +97,10 @@ private:
bool matchCategory(const BitTorrent::TorrentHandle *torrent) const; bool matchCategory(const BitTorrent::TorrentHandle *torrent) const;
bool matchTag(const BitTorrent::TorrentHandle *torrent) const; bool matchTag(const BitTorrent::TorrentHandle *torrent) const;
Type m_type; Type m_type {All};
QString m_category; QString m_category;
QString m_tag; QString m_tag;
QStringSet m_hashSet; InfoHashSet m_hashSet;
}; };
#endif // TORRENTFILTER_H #endif // TORRENTFILTER_H

6
src/gui/mainwindow.cpp

@ -264,11 +264,11 @@ MainWindow::MainWindow(QWidget *parent)
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerlessStateChanged, m_transferListFiltersWidget, &TransferListFiltersWidget::changeTrackerless); connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerlessStateChanged, m_transferListFiltersWidget, &TransferListFiltersWidget::changeTrackerless);
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerSuccess connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerSuccess
, m_transferListFiltersWidget, qOverload<BitTorrent::TorrentHandle *const, const QString &>(&TransferListFiltersWidget::trackerSuccess)); , m_transferListFiltersWidget, qOverload<const BitTorrent::TorrentHandle *, const QString &>(&TransferListFiltersWidget::trackerSuccess));
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerError connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerError
, m_transferListFiltersWidget, qOverload<BitTorrent::TorrentHandle *const, const QString &>(&TransferListFiltersWidget::trackerError)); , m_transferListFiltersWidget, qOverload<const BitTorrent::TorrentHandle *, const QString &>(&TransferListFiltersWidget::trackerError));
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerWarning connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerWarning
, m_transferListFiltersWidget, qOverload<BitTorrent::TorrentHandle *const, const QString &>(&TransferListFiltersWidget::trackerWarning)); , m_transferListFiltersWidget, qOverload<const BitTorrent::TorrentHandle *, const QString &>(&TransferListFiltersWidget::trackerWarning));
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
// Increase top spacing to avoid tab overlapping // Increase top spacing to avoid tab overlapping

194
src/gui/transferlistfilterswidget.cpp

@ -74,6 +74,19 @@ namespace
return scheme; return scheme;
} }
QString getHost(const QString &tracker)
{
// We want the domain + tld. Subdomains should be disregarded
const QUrl url {tracker};
const QString host {url.host()};
// host is in IP format
if (!QHostAddress(host).isNull())
return host;
return host.section('.', -2, -1);
}
class ArrowCheckBox final : public QCheckBox class ArrowCheckBox final : public QCheckBox
{ {
public: public:
@ -97,6 +110,8 @@ namespace
style()->drawControl(QStyle::CE_CheckBoxLabel, &labelOption, &painter, this); style()->drawControl(QStyle::CE_CheckBoxLabel, &labelOption, &painter, this);
} }
}; };
const QString NULL_HOST {""};
} }
BaseFilterWidget::BaseFilterWidget(QWidget *parent, TransferListWidget *transferList) BaseFilterWidget::BaseFilterWidget(QWidget *parent, TransferListWidget *transferList)
@ -294,7 +309,7 @@ TrackerFiltersList::TrackerFiltersList(QWidget *parent, TransferListWidget *tran
auto *warningTracker = new QListWidgetItem(this); auto *warningTracker = new QListWidgetItem(this);
warningTracker->setData(Qt::DisplayRole, tr("Warning (0)")); warningTracker->setData(Qt::DisplayRole, tr("Warning (0)"));
warningTracker->setData(Qt::DecorationRole, style()->standardIcon(QStyle::SP_MessageBoxWarning)); warningTracker->setData(Qt::DecorationRole, style()->standardIcon(QStyle::SP_MessageBoxWarning));
m_trackers.insert("", QStringList()); m_trackers[NULL_HOST] = {};
setCurrentRow(0, QItemSelectionModel::SelectCurrent); setCurrentRow(0, QItemSelectionModel::SelectCurrent);
toggleFilter(Preferences::instance()->getTrackerFilterState()); toggleFilter(Preferences::instance()->getTrackerFilterState());
@ -306,27 +321,20 @@ TrackerFiltersList::~TrackerFiltersList()
Utils::Fs::forceRemove(iconPath); Utils::Fs::forceRemove(iconPath);
} }
void TrackerFiltersList::addItem(const QString &tracker, const QString &hash) void TrackerFiltersList::addItem(const QString &tracker, const BitTorrent::InfoHash &hash)
{ {
QStringList tmp; const QString host {getHost(tracker)};
QListWidgetItem *trackerItem = nullptr; const bool exists {m_trackers.contains(host)};
QString host = getHost(tracker); QListWidgetItem *trackerItem {nullptr};
bool exists = m_trackers.contains(host);
if (exists) if (exists)
{ {
tmp = m_trackers.value(host); if (m_trackers.value(host).contains(hash))
if (tmp.contains(hash))
return; return;
if (host != "") trackerItem = item((host == NULL_HOST)
{ ? TRACKERLESS_ROW
trackerItem = item(rowFromTracker(host)); : rowFromTracker(host));
}
else
{
trackerItem = item(TRACKERLESS_ROW);
}
} }
else else
{ {
@ -338,17 +346,18 @@ void TrackerFiltersList::addItem(const QString &tracker, const QString &hash)
} }
if (!trackerItem) return; if (!trackerItem) return;
tmp.append(hash); QSet<BitTorrent::InfoHash> &hashes {m_trackers[host]};
m_trackers.insert(host, tmp); hashes.insert(hash);
if (host == "")
if (host == NULL_HOST)
{ {
trackerItem->setText(tr("Trackerless (%1)").arg(tmp.size())); trackerItem->setText(tr("Trackerless (%1)").arg(hashes.size()));
if (currentRow() == TRACKERLESS_ROW) if (currentRow() == TRACKERLESS_ROW)
applyFilter(TRACKERLESS_ROW); applyFilter(TRACKERLESS_ROW);
return; return;
} }
trackerItem->setText(QString::fromLatin1("%1 (%2)").arg(host, QString::number(tmp.size()))); trackerItem->setText(QString::fromLatin1("%1 (%2)").arg(host, QString::number(hashes.size())));
if (exists) if (exists)
{ {
if (currentRow() == rowFromTracker(host)) if (currentRow() == rowFromTracker(host))
@ -370,16 +379,17 @@ void TrackerFiltersList::addItem(const QString &tracker, const QString &hash)
updateGeometry(); updateGeometry();
} }
void TrackerFiltersList::removeItem(const QString &tracker, const QString &hash) void TrackerFiltersList::removeItem(const QString &tracker, const BitTorrent::InfoHash &hash)
{ {
QString host = getHost(tracker); const QString host = getHost(tracker);
QListWidgetItem *trackerItem = nullptr; QSet<BitTorrent::InfoHash> hashes = m_trackers.value(host);
QStringList tmp = m_trackers.value(host);
int row = 0;
if (tmp.empty()) if (hashes.empty())
return; return;
tmp.removeAll(hash); hashes.remove(hash);
int row = 0;
QListWidgetItem *trackerItem = nullptr;
if (!host.isEmpty()) if (!host.isEmpty())
{ {
@ -387,7 +397,8 @@ void TrackerFiltersList::removeItem(const QString &tracker, const QString &hash)
trackerSuccess(hash, tracker); trackerSuccess(hash, tracker);
row = rowFromTracker(host); row = rowFromTracker(host);
trackerItem = item(row); trackerItem = item(row);
if (tmp.empty())
if (hashes.empty())
{ {
if (currentRow() == row) if (currentRow() == row)
setCurrentRow(0, QItemSelectionModel::SelectCurrent); setCurrentRow(0, QItemSelectionModel::SelectCurrent);
@ -396,27 +407,29 @@ void TrackerFiltersList::removeItem(const QString &tracker, const QString &hash)
updateGeometry(); updateGeometry();
return; return;
} }
if (trackerItem) if (trackerItem)
trackerItem->setText(QString::fromLatin1("%1 (%2)").arg(host, QString::number(tmp.size()))); trackerItem->setText(QString::fromLatin1("%1 (%2)").arg(host, QString::number(hashes.size())));
} }
else else
{ {
row = 1; row = 1;
trackerItem = item(TRACKERLESS_ROW); trackerItem = item(TRACKERLESS_ROW);
trackerItem->setText(tr("Trackerless (%1)").arg(tmp.size())); trackerItem->setText(tr("Trackerless (%1)").arg(hashes.size()));
} }
m_trackers.insert(host, tmp); m_trackers.insert(host, hashes);
if (currentRow() == row) if (currentRow() == row)
applyFilter(row); applyFilter(row);
} }
void TrackerFiltersList::changeTrackerless(bool trackerless, const QString &hash) void TrackerFiltersList::changeTrackerless(const bool trackerless, const BitTorrent::InfoHash &hash)
{ {
if (trackerless) if (trackerless)
addItem("", hash); addItem(NULL_HOST, hash);
else else
removeItem("", hash); removeItem(NULL_HOST, hash);
} }
void TrackerFiltersList::setDownloadTrackerFavicon(bool value) void TrackerFiltersList::setDownloadTrackerFavicon(bool value)
@ -439,70 +452,57 @@ void TrackerFiltersList::setDownloadTrackerFavicon(bool value)
} }
} }
void TrackerFiltersList::trackerSuccess(const QString &hash, const QString &tracker) void TrackerFiltersList::trackerSuccess(const BitTorrent::InfoHash &hash, const QString &tracker)
{ {
QStringList errored = m_errors.value(hash); const auto errorHashesIter = m_errors.find(hash);
QStringList warned = m_warnings.value(hash); if (errorHashesIter != m_errors.end())
if (errored.contains(tracker))
{ {
errored.removeAll(tracker); QSet<QString> &errored = *errorHashesIter;
errored.remove(tracker);
if (errored.empty()) if (errored.empty())
{ {
m_errors.remove(hash); m_errors.erase(errorHashesIter);
item(ERROR_ROW)->setText(tr("Error (%1)").arg(m_errors.size())); item(ERROR_ROW)->setText(tr("Error (%1)").arg(m_errors.size()));
if (currentRow() == ERROR_ROW) if (currentRow() == ERROR_ROW)
applyFilter(ERROR_ROW); applyFilter(ERROR_ROW);
} }
else
{
m_errors.insert(hash, errored);
}
} }
if (warned.contains(tracker)) const auto warningHashesIter = m_warnings.find(hash);
if (warningHashesIter != m_warnings.end())
{ {
warned.removeAll(tracker); QSet<QString> &warned = *warningHashesIter;
warned.remove(tracker);
if (warned.empty()) if (warned.empty())
{ {
m_warnings.remove(hash); m_warnings.erase(warningHashesIter);
item(WARNING_ROW)->setText(tr("Warning (%1)").arg(m_warnings.size())); item(WARNING_ROW)->setText(tr("Warning (%1)").arg(m_warnings.size()));
if (currentRow() == WARNING_ROW) if (currentRow() == WARNING_ROW)
applyFilter(WARNING_ROW); applyFilter(WARNING_ROW);
} }
else
{
m_warnings.insert(hash, warned);
}
} }
} }
void TrackerFiltersList::trackerError(const QString &hash, const QString &tracker) void TrackerFiltersList::trackerError(const BitTorrent::InfoHash &hash, const QString &tracker)
{ {
QStringList trackers = m_errors.value(hash); QSet<QString> &trackers {m_errors[hash]};
if (trackers.contains(tracker)) if (trackers.contains(tracker))
return; return;
trackers.append(tracker); trackers.insert(tracker);
m_errors.insert(hash, trackers);
item(ERROR_ROW)->setText(tr("Error (%1)").arg(m_errors.size())); item(ERROR_ROW)->setText(tr("Error (%1)").arg(m_errors.size()));
if (currentRow() == ERROR_ROW) if (currentRow() == ERROR_ROW)
applyFilter(ERROR_ROW); applyFilter(ERROR_ROW);
} }
void TrackerFiltersList::trackerWarning(const QString &hash, const QString &tracker) void TrackerFiltersList::trackerWarning(const BitTorrent::InfoHash &hash, const QString &tracker)
{ {
QStringList trackers = m_warnings.value(hash); QSet<QString> &trackers {m_warnings[hash]};
if (trackers.contains(tracker)) if (trackers.contains(tracker))
return; return;
trackers.append(tracker); trackers.insert(tracker);
m_warnings.insert(hash, trackers);
item(WARNING_ROW)->setText(tr("Warning (%1)").arg(m_warnings.size())); item(WARNING_ROW)->setText(tr("Warning (%1)").arg(m_warnings.size()));
if (currentRow() == WARNING_ROW) if (currentRow() == WARNING_ROW)
applyFilter(WARNING_ROW); applyFilter(WARNING_ROW);
} }
@ -574,33 +574,33 @@ void TrackerFiltersList::applyFilter(const int row)
if (row == ALL_ROW) if (row == ALL_ROW)
transferList->applyTrackerFilterAll(); transferList->applyTrackerFilterAll();
else if (isVisible()) else if (isVisible())
transferList->applyTrackerFilter(getHashes(row)); transferList->applyTrackerFilter(getInfoHashes(row));
} }
void TrackerFiltersList::handleNewTorrent(BitTorrent::TorrentHandle *const torrent) void TrackerFiltersList::handleNewTorrent(BitTorrent::TorrentHandle *const torrent)
{ {
QString hash = torrent->hash(); const BitTorrent::InfoHash hash {torrent->hash()};
const QVector<BitTorrent::TrackerEntry> trackers = torrent->trackers(); const QVector<BitTorrent::TrackerEntry> trackers {torrent->trackers()};
for (const BitTorrent::TrackerEntry &tracker : trackers) for (const BitTorrent::TrackerEntry &tracker : trackers)
addItem(tracker.url(), hash); addItem(tracker.url(), hash);
//Check for trackerless torrent // Check for trackerless torrent
if (trackers.isEmpty()) if (trackers.isEmpty())
addItem("", hash); addItem(NULL_HOST, hash);
item(ALL_ROW)->setText(tr("All (%1)", "this is for the tracker filter").arg(++m_totalTorrents)); item(ALL_ROW)->setText(tr("All (%1)", "this is for the tracker filter").arg(++m_totalTorrents));
} }
void TrackerFiltersList::torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const torrent) void TrackerFiltersList::torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const torrent)
{ {
QString hash = torrent->hash(); const BitTorrent::InfoHash hash {torrent->hash()};
const QVector<BitTorrent::TrackerEntry> trackers = torrent->trackers(); const QVector<BitTorrent::TrackerEntry> trackers {torrent->trackers()};
for (const BitTorrent::TrackerEntry &tracker : trackers) for (const BitTorrent::TrackerEntry &tracker : trackers)
removeItem(tracker.url(), hash); removeItem(tracker.url(), hash);
//Check for trackerless torrent // Check for trackerless torrent
if (trackers.isEmpty()) if (trackers.isEmpty())
removeItem("", hash); removeItem(NULL_HOST, hash);
item(ALL_ROW)->setText(tr("All (%1)", "this is for the tracker filter").arg(--m_totalTorrents)); item(ALL_ROW)->setText(tr("All (%1)", "this is for the tracker filter").arg(--m_totalTorrents));
} }
@ -618,34 +618,24 @@ QString TrackerFiltersList::trackerFromRow(int row) const
int TrackerFiltersList::rowFromTracker(const QString &tracker) const int TrackerFiltersList::rowFromTracker(const QString &tracker) const
{ {
Q_ASSERT(!tracker.isEmpty()); Q_ASSERT(!tracker.isEmpty());
for (int i = 4; i<count(); ++i) for (int i = 4; i < count(); ++i)
if (tracker == trackerFromRow(i)) return i; {
if (tracker == trackerFromRow(i))
return i;
}
return -1; return -1;
} }
QString TrackerFiltersList::getHost(const QString &tracker) const QSet<BitTorrent::InfoHash> TrackerFiltersList::getInfoHashes(const int row) const
{
// We want the domain + tld. Subdomains should be disregarded
const QUrl url {tracker};
const QString host {url.host()};
// host is in IP format
if (!QHostAddress(host).isNull())
return host;
return host.section('.', -2, -1);
}
QStringList TrackerFiltersList::getHashes(const int row) const
{ {
switch (row) switch (row)
{ {
case TRACKERLESS_ROW: case TRACKERLESS_ROW:
return m_trackers.value(""); return m_trackers.value(NULL_HOST);
case ERROR_ROW: case ERROR_ROW:
return m_errors.keys(); return List::toSet(m_errors.keys());
case WARNING_ROW: case WARNING_ROW:
return m_warnings.keys(); return List::toSet(m_warnings.keys());
default: default:
return m_trackers.value(trackerFromRow(row)); return m_trackers.value(trackerFromRow(row));
} }
@ -739,11 +729,11 @@ TransferListFiltersWidget::TransferListFiltersWidget(QWidget *parent, TransferLi
connect(trackerLabel, &QCheckBox::toggled, m_trackerFilters, &TrackerFiltersList::toggleFilter); connect(trackerLabel, &QCheckBox::toggled, m_trackerFilters, &TrackerFiltersList::toggleFilter);
connect(trackerLabel, &QCheckBox::toggled, pref, &Preferences::setTrackerFilterState); connect(trackerLabel, &QCheckBox::toggled, pref, &Preferences::setTrackerFilterState);
connect(this, qOverload<const QString &, const QString &>(&TransferListFiltersWidget::trackerSuccess) connect(this, qOverload<const BitTorrent::InfoHash &, const QString &>(&TransferListFiltersWidget::trackerSuccess)
, m_trackerFilters, &TrackerFiltersList::trackerSuccess); , m_trackerFilters, &TrackerFiltersList::trackerSuccess);
connect(this, qOverload<const QString &, const QString &>(&TransferListFiltersWidget::trackerError) connect(this, qOverload<const BitTorrent::InfoHash &, const QString &>(&TransferListFiltersWidget::trackerError)
, m_trackerFilters, &TrackerFiltersList::trackerError); , m_trackerFilters, &TrackerFiltersList::trackerError);
connect(this, qOverload<const QString &, const QString &>(&TransferListFiltersWidget::trackerWarning) connect(this, qOverload<const BitTorrent::InfoHash &, const QString &>(&TransferListFiltersWidget::trackerWarning)
, m_trackerFilters, &TrackerFiltersList::trackerWarning); , m_trackerFilters, &TrackerFiltersList::trackerWarning);
} }
@ -752,34 +742,34 @@ void TransferListFiltersWidget::setDownloadTrackerFavicon(bool value)
m_trackerFilters->setDownloadTrackerFavicon(value); m_trackerFilters->setDownloadTrackerFavicon(value);
} }
void TransferListFiltersWidget::addTrackers(BitTorrent::TorrentHandle *const torrent, const QVector<BitTorrent::TrackerEntry> &trackers) void TransferListFiltersWidget::addTrackers(const BitTorrent::TorrentHandle *torrent, const QVector<BitTorrent::TrackerEntry> &trackers)
{ {
for (const BitTorrent::TrackerEntry &tracker : trackers) for (const BitTorrent::TrackerEntry &tracker : trackers)
m_trackerFilters->addItem(tracker.url(), torrent->hash()); m_trackerFilters->addItem(tracker.url(), torrent->hash());
} }
void TransferListFiltersWidget::removeTrackers(BitTorrent::TorrentHandle *const torrent, const QVector<BitTorrent::TrackerEntry> &trackers) void TransferListFiltersWidget::removeTrackers(const BitTorrent::TorrentHandle *torrent, const QVector<BitTorrent::TrackerEntry> &trackers)
{ {
for (const BitTorrent::TrackerEntry &tracker : trackers) for (const BitTorrent::TrackerEntry &tracker : trackers)
m_trackerFilters->removeItem(tracker.url(), torrent->hash()); m_trackerFilters->removeItem(tracker.url(), torrent->hash());
} }
void TransferListFiltersWidget::changeTrackerless(BitTorrent::TorrentHandle *const torrent, bool trackerless) void TransferListFiltersWidget::changeTrackerless(const BitTorrent::TorrentHandle *torrent, const bool trackerless)
{ {
m_trackerFilters->changeTrackerless(trackerless, torrent->hash()); m_trackerFilters->changeTrackerless(trackerless, torrent->hash());
} }
void TransferListFiltersWidget::trackerSuccess(BitTorrent::TorrentHandle *const torrent, const QString &tracker) void TransferListFiltersWidget::trackerSuccess(const BitTorrent::TorrentHandle *torrent, const QString &tracker)
{ {
emit trackerSuccess(torrent->hash(), tracker); emit trackerSuccess(torrent->hash(), tracker);
} }
void TransferListFiltersWidget::trackerWarning(BitTorrent::TorrentHandle *const torrent, const QString &tracker) void TransferListFiltersWidget::trackerWarning(const BitTorrent::TorrentHandle *torrent, const QString &tracker)
{ {
emit trackerWarning(torrent->hash(), tracker); emit trackerWarning(torrent->hash(), tracker);
} }
void TransferListFiltersWidget::trackerError(BitTorrent::TorrentHandle *const torrent, const QString &tracker) void TransferListFiltersWidget::trackerError(const BitTorrent::TorrentHandle *torrent, const QString &tracker)
{ {
emit trackerError(torrent->hash(), tracker); emit trackerError(torrent->hash(), tracker);
} }

44
src/gui/transferlistfilterswidget.h

@ -31,6 +31,7 @@
#include <QFrame> #include <QFrame>
#include <QListWidget> #include <QListWidget>
#include <QtContainerFwd>
class QCheckBox; class QCheckBox;
class QResizeEvent; class QResizeEvent;
@ -39,6 +40,7 @@ class TransferListWidget;
namespace BitTorrent namespace BitTorrent
{ {
class InfoHash;
class TorrentHandle; class TorrentHandle;
class TrackerEntry; class TrackerEntry;
} }
@ -103,15 +105,15 @@ public:
~TrackerFiltersList() override; ~TrackerFiltersList() override;
// Redefine addItem() to make sure the list stays sorted // Redefine addItem() to make sure the list stays sorted
void addItem(const QString &tracker, const QString &hash); void addItem(const QString &tracker, const BitTorrent::InfoHash &hash);
void removeItem(const QString &tracker, const QString &hash); void removeItem(const QString &tracker, const BitTorrent::InfoHash &hash);
void changeTrackerless(bool trackerless, const QString &hash); void changeTrackerless(bool trackerless, const BitTorrent::InfoHash &hash);
void setDownloadTrackerFavicon(bool value); void setDownloadTrackerFavicon(bool value);
public slots: public slots:
void trackerSuccess(const QString &hash, const QString &tracker); void trackerSuccess(const BitTorrent::InfoHash &hash, const QString &tracker);
void trackerError(const QString &hash, const QString &tracker); void trackerError(const BitTorrent::InfoHash &hash, const QString &tracker);
void trackerWarning(const QString &hash, const QString &tracker); void trackerWarning(const BitTorrent::InfoHash &hash, const QString &tracker);
private slots: private slots:
void handleFavicoDownloadFinished(const Net::DownloadResult &result); void handleFavicoDownloadFinished(const Net::DownloadResult &result);
@ -125,13 +127,12 @@ private:
void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const torrent) override; void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const torrent) override;
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 &tracker) const; QSet<BitTorrent::InfoHash> getInfoHashes(int row) const;
QStringList getHashes(int row) const;
void downloadFavicon(const QString &url); void downloadFavicon(const QString &url);
QHash<QString, QStringList> m_trackers; QHash<QString, QSet<BitTorrent::InfoHash>> m_trackers; // <tracker host, torrent hashes>
QHash<QString, QStringList> m_errors; QHash<BitTorrent::InfoHash, QSet<QString>> m_errors; // <torrent hash, tracker hosts>
QHash<QString, QStringList> m_warnings; QHash<BitTorrent::InfoHash, QSet<QString>> m_warnings; // <torrent hash, tracker hosts>
QStringList m_iconPaths; QStringList m_iconPaths;
int m_totalTorrents; int m_totalTorrents;
bool m_downloadTrackerFavicon; bool m_downloadTrackerFavicon;
@ -140,26 +141,27 @@ private:
class CategoryFilterWidget; class CategoryFilterWidget;
class TagFilterWidget; class TagFilterWidget;
class TransferListFiltersWidget : public QFrame class TransferListFiltersWidget final : public QFrame
{ {
Q_OBJECT Q_OBJECT
Q_DISABLE_COPY(TransferListFiltersWidget)
public: public:
TransferListFiltersWidget(QWidget *parent, TransferListWidget *transferList, bool downloadFavicon); TransferListFiltersWidget(QWidget *parent, TransferListWidget *transferList, bool downloadFavicon);
void setDownloadTrackerFavicon(bool value); void setDownloadTrackerFavicon(bool value);
public slots: public slots:
void addTrackers(BitTorrent::TorrentHandle *const torrent, const QVector<BitTorrent::TrackerEntry> &trackers); void addTrackers(const BitTorrent::TorrentHandle *torrent, const QVector<BitTorrent::TrackerEntry> &trackers);
void removeTrackers(BitTorrent::TorrentHandle *const torrent, const QVector<BitTorrent::TrackerEntry> &trackers); void removeTrackers(const BitTorrent::TorrentHandle *torrent, const QVector<BitTorrent::TrackerEntry> &trackers);
void changeTrackerless(BitTorrent::TorrentHandle *const torrent, bool trackerless); void changeTrackerless(const BitTorrent::TorrentHandle *torrent, bool trackerless);
void trackerSuccess(BitTorrent::TorrentHandle *const torrent, const QString &tracker); void trackerSuccess(const BitTorrent::TorrentHandle *torrent, const QString &tracker);
void trackerWarning(BitTorrent::TorrentHandle *const torrent, const QString &tracker); void trackerWarning(const BitTorrent::TorrentHandle *torrent, const QString &tracker);
void trackerError(BitTorrent::TorrentHandle *const torrent, const QString &tracker); void trackerError(const BitTorrent::TorrentHandle *torrent, const QString &tracker);
signals: signals:
void trackerSuccess(const QString &hash, const QString &tracker); void trackerSuccess(const BitTorrent::InfoHash &hash, const QString &tracker);
void trackerError(const QString &hash, const QString &tracker); void trackerError(const BitTorrent::InfoHash &hash, const QString &tracker);
void trackerWarning(const QString &hash, const QString &tracker); void trackerWarning(const BitTorrent::InfoHash &hash, const QString &tracker);
private slots: private slots:
void onCategoryFilterStateChanged(bool enabled); void onCategoryFilterStateChanged(bool enabled);

5
src/gui/transferlistsortmodel.cpp

@ -29,7 +29,6 @@
#include "transferlistsortmodel.h" #include "transferlistsortmodel.h"
#include <QDateTime> #include <QDateTime>
#include <QStringList>
#include "base/bittorrent/infohash.h" #include "base/bittorrent/infohash.h"
#include "base/bittorrent/torrenthandle.h" #include "base/bittorrent/torrenthandle.h"
@ -75,9 +74,9 @@ void TransferListSortModel::disableTagFilter()
invalidateFilter(); invalidateFilter();
} }
void TransferListSortModel::setTrackerFilter(const QStringList &hashes) void TransferListSortModel::setTrackerFilter(const QSet<BitTorrent::InfoHash> &hashes)
{ {
if (m_filter.setHashSet(List::toSet(hashes))) if (m_filter.setHashSet(hashes))
invalidateFilter(); invalidateFilter();
} }

7
src/gui/transferlistsortmodel.h

@ -31,7 +31,10 @@
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include "base/torrentfilter.h" #include "base/torrentfilter.h"
class QStringList; namespace BitTorrent
{
class InfoHash;
}
class TransferListSortModel final : public QSortFilterProxyModel class TransferListSortModel final : public QSortFilterProxyModel
{ {
@ -46,7 +49,7 @@ public:
void disableCategoryFilter(); void disableCategoryFilter();
void setTagFilter(const QString &tag); void setTagFilter(const QString &tag);
void disableTagFilter(); void disableTagFilter();
void setTrackerFilter(const QStringList &hashes); void setTrackerFilter(const QSet<BitTorrent::InfoHash> &hashes);
void disableTrackerFilter(); void disableTrackerFilter();
private: private:

3
src/gui/transferlistwidget.cpp

@ -41,6 +41,7 @@
#include <QSet> #include <QSet>
#include <QShortcut> #include <QShortcut>
#include <QTableView> #include <QTableView>
#include <QVector>
#include <QWheelEvent> #include <QWheelEvent>
#include "base/bittorrent/infohash.h" #include "base/bittorrent/infohash.h"
@ -1226,7 +1227,7 @@ void TransferListWidget::applyTrackerFilterAll()
m_sortFilterModel->disableTrackerFilter(); m_sortFilterModel->disableTrackerFilter();
} }
void TransferListWidget::applyTrackerFilter(const QStringList &hashes) void TransferListWidget::applyTrackerFilter(const QSet<BitTorrent::InfoHash> &hashes)
{ {
m_sortFilterModel->setTrackerFilter(hashes); m_sortFilterModel->setTrackerFilter(hashes);
} }

5
src/gui/transferlistwidget.h

@ -30,8 +30,8 @@
#define TRANSFERLISTWIDGET_H #define TRANSFERLISTWIDGET_H
#include <functional> #include <functional>
#include <QtContainerFwd>
#include <QTreeView> #include <QTreeView>
#include <QVector>
class MainWindow; class MainWindow;
class TransferListDelegate; class TransferListDelegate;
@ -40,6 +40,7 @@ class TransferListSortModel;
namespace BitTorrent namespace BitTorrent
{ {
class InfoHash;
class TorrentHandle; class TorrentHandle;
} }
@ -90,7 +91,7 @@ public slots:
void applyCategoryFilter(const QString &category); void applyCategoryFilter(const QString &category);
void applyTagFilter(const QString &tag); void applyTagFilter(const QString &tag);
void applyTrackerFilterAll(); void applyTrackerFilterAll();
void applyTrackerFilter(const QStringList &hashes); void applyTrackerFilter(const QSet<BitTorrent::InfoHash> &hashes);
void previewFile(const QString &filePath); void previewFile(const QString &filePath);
void renameSelectedTorrent(); void renameSelectedTorrent();

8
src/webui/api/torrentscontroller.cpp

@ -256,10 +256,14 @@ void TorrentsController::infoAction()
const bool reverse {parseBool(params()["reverse"], false)}; const bool reverse {parseBool(params()["reverse"], false)};
int limit {params()["limit"].toInt()}; int limit {params()["limit"].toInt()};
int offset {params()["offset"].toInt()}; int offset {params()["offset"].toInt()};
const QStringSet hashSet {List::toSet(params()["hashes"].split('|', QString::SkipEmptyParts))}; const QStringList hashes {params()["hashes"].split('|', QString::SkipEmptyParts)};
InfoHashSet hashSet;
for (const QString &hash : hashes)
hashSet.insert(BitTorrent::InfoHash {hash});
QVariantList torrentList; QVariantList torrentList;
TorrentFilter torrentFilter(filter, (hashSet.isEmpty() ? TorrentFilter::AnyHash : hashSet), category); TorrentFilter torrentFilter(filter, (hashes.isEmpty() ? TorrentFilter::AnyHash : hashSet), category);
for (BitTorrent::TorrentHandle *const torrent : asConst(BitTorrent::Session::instance()->torrents())) for (BitTorrent::TorrentHandle *const torrent : asConst(BitTorrent::Session::instance()->torrents()))
{ {
if (torrentFilter.match(torrent)) if (torrentFilter.match(torrent))

Loading…
Cancel
Save