mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-11 15:27:54 +00:00
Merge pull request #16587 from jagannatharjun/tracker-filter
Optimize torrent filters in GUI
This commit is contained in:
commit
85b0a40a0e
@ -2090,6 +2090,11 @@ QVector<Torrent *> Session::torrents() const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qsizetype Session::torrentsCount() const
|
||||||
|
{
|
||||||
|
return m_torrents.size();
|
||||||
|
}
|
||||||
|
|
||||||
bool Session::addTorrent(const QString &source, const AddTorrentParams ¶ms)
|
bool Session::addTorrent(const QString &source, const AddTorrentParams ¶ms)
|
||||||
{
|
{
|
||||||
// `source`: .torrent file path/url or magnet uri
|
// `source`: .torrent file path/url or magnet uri
|
||||||
|
@ -463,6 +463,7 @@ namespace BitTorrent
|
|||||||
void startUpTorrents();
|
void startUpTorrents();
|
||||||
Torrent *findTorrent(const TorrentID &id) const;
|
Torrent *findTorrent(const TorrentID &id) const;
|
||||||
QVector<Torrent *> torrents() const;
|
QVector<Torrent *> torrents() const;
|
||||||
|
qsizetype torrentsCount() const;
|
||||||
bool hasActiveTorrents() const;
|
bool hasActiveTorrents() const;
|
||||||
bool hasUnfinishedTorrents() const;
|
bool hasUnfinishedTorrents() const;
|
||||||
bool hasRunningSeed() const;
|
bool hasRunningSeed() const;
|
||||||
|
@ -217,6 +217,7 @@ namespace BitTorrent
|
|||||||
virtual bool hasMissingFiles() const = 0;
|
virtual bool hasMissingFiles() const = 0;
|
||||||
virtual bool hasError() const = 0;
|
virtual bool hasError() const = 0;
|
||||||
virtual int queuePosition() const = 0;
|
virtual int queuePosition() const = 0;
|
||||||
|
virtual QVector<QString> trackerURLs() const = 0;
|
||||||
virtual QVector<TrackerEntry> trackers() const = 0;
|
virtual QVector<TrackerEntry> trackers() const = 0;
|
||||||
virtual QVector<QUrl> urlSeeds() const = 0;
|
virtual QVector<QUrl> urlSeeds() const = 0;
|
||||||
virtual QString error() const = 0;
|
virtual QString error() const = 0;
|
||||||
|
@ -517,6 +517,22 @@ void TorrentImpl::setAutoManaged(const bool enable)
|
|||||||
m_nativeHandle.unset_flags(lt::torrent_flags::auto_managed);
|
m_nativeHandle.unset_flags(lt::torrent_flags::auto_managed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<QString> TorrentImpl::trackerURLs() const
|
||||||
|
{
|
||||||
|
const std::vector<lt::announce_entry> nativeTrackers = m_nativeHandle.trackers();
|
||||||
|
|
||||||
|
QVector<QString> urls;
|
||||||
|
urls.reserve(static_cast<decltype(urls)::size_type>(nativeTrackers.size()));
|
||||||
|
|
||||||
|
for (const lt::announce_entry &tracker : nativeTrackers)
|
||||||
|
{
|
||||||
|
const QString trackerURL = QString::fromStdString(tracker.url);
|
||||||
|
urls.push_back(trackerURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return urls;
|
||||||
|
}
|
||||||
|
|
||||||
QVector<TrackerEntry> TorrentImpl::trackers() const
|
QVector<TrackerEntry> TorrentImpl::trackers() const
|
||||||
{
|
{
|
||||||
const std::vector<lt::announce_entry> nativeTrackers = m_nativeHandle.trackers();
|
const std::vector<lt::announce_entry> nativeTrackers = m_nativeHandle.trackers();
|
||||||
|
@ -153,6 +153,7 @@ namespace BitTorrent
|
|||||||
bool hasMissingFiles() const override;
|
bool hasMissingFiles() const override;
|
||||||
bool hasError() const override;
|
bool hasError() const override;
|
||||||
int queuePosition() const override;
|
int queuePosition() const override;
|
||||||
|
QVector<QString> trackerURLs() const override;
|
||||||
QVector<TrackerEntry> trackers() const override;
|
QVector<TrackerEntry> trackers() const override;
|
||||||
QVector<QUrl> urlSeeds() const override;
|
QVector<QUrl> urlSeeds() const override;
|
||||||
QString error() const override;
|
QString error() const override;
|
||||||
|
@ -50,8 +50,7 @@ public:
|
|||||||
{
|
{
|
||||||
m_dataPtr->valid = true;
|
m_dataPtr->valid = true;
|
||||||
m_dataPtr->nativeDigest = nativeDigest;
|
m_dataPtr->nativeDigest = nativeDigest;
|
||||||
const QByteArray raw = QByteArray::fromRawData(nativeDigest.data(), length());
|
m_dataPtr->hashString.clear(); // hashString is created on demand
|
||||||
m_dataPtr->hashString = QString::fromLatin1(raw.toHex());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr int length()
|
static constexpr int length()
|
||||||
@ -91,6 +90,12 @@ public:
|
|||||||
|
|
||||||
QString toString() const
|
QString toString() const
|
||||||
{
|
{
|
||||||
|
if (m_dataPtr->hashString.isEmpty())
|
||||||
|
{
|
||||||
|
const QByteArray raw = QByteArray::fromRawData(m_dataPtr->nativeDigest.data(), length());
|
||||||
|
const_cast<Digest32 *>(this)->m_dataPtr->hashString = QString::fromLatin1(raw.toHex());
|
||||||
|
}
|
||||||
|
|
||||||
return m_dataPtr->hashString;
|
return m_dataPtr->hashString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,13 +169,6 @@ void BaseFilterWidget::toggleFilter(bool checked)
|
|||||||
StatusFilterWidget::StatusFilterWidget(QWidget *parent, TransferListWidget *transferList)
|
StatusFilterWidget::StatusFilterWidget(QWidget *parent, TransferListWidget *transferList)
|
||||||
: BaseFilterWidget(parent, transferList)
|
: BaseFilterWidget(parent, transferList)
|
||||||
{
|
{
|
||||||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentLoaded
|
|
||||||
, this, &StatusFilterWidget::updateTorrentNumbers);
|
|
||||||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentsUpdated
|
|
||||||
, this, &StatusFilterWidget::updateTorrentNumbers);
|
|
||||||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentAboutToBeRemoved
|
|
||||||
, this, &StatusFilterWidget::updateTorrentNumbers);
|
|
||||||
|
|
||||||
// Add status filters
|
// Add status filters
|
||||||
auto *all = new QListWidgetItem(this);
|
auto *all = new QListWidgetItem(this);
|
||||||
all->setData(Qt::DisplayRole, tr("All (0)", "this is for the status filter"));
|
all->setData(Qt::DisplayRole, tr("All (0)", "this is for the status filter"));
|
||||||
@ -220,6 +213,11 @@ StatusFilterWidget::StatusFilterWidget(QWidget *parent, TransferListWidget *tran
|
|||||||
const Preferences *const pref = Preferences::instance();
|
const Preferences *const pref = Preferences::instance();
|
||||||
setCurrentRow(pref->getTransSelFilter(), QItemSelectionModel::SelectCurrent);
|
setCurrentRow(pref->getTransSelFilter(), QItemSelectionModel::SelectCurrent);
|
||||||
toggleFilter(pref->getStatusFilterState());
|
toggleFilter(pref->getStatusFilterState());
|
||||||
|
|
||||||
|
populate();
|
||||||
|
|
||||||
|
connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentsUpdated
|
||||||
|
, this, &StatusFilterWidget::handleTorrentsUpdated);
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusFilterWidget::~StatusFilterWidget()
|
StatusFilterWidget::~StatusFilterWidget()
|
||||||
@ -227,63 +225,87 @@ StatusFilterWidget::~StatusFilterWidget()
|
|||||||
Preferences::instance()->setTransSelFilter(currentRow());
|
Preferences::instance()->setTransSelFilter(currentRow());
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusFilterWidget::updateTorrentNumbers()
|
void StatusFilterWidget::populate()
|
||||||
{
|
{
|
||||||
int nbDownloading = 0;
|
m_torrentsStatus.clear();
|
||||||
int nbSeeding = 0;
|
|
||||||
int nbCompleted = 0;
|
|
||||||
int nbResumed = 0;
|
|
||||||
int nbPaused = 0;
|
|
||||||
int nbActive = 0;
|
|
||||||
int nbInactive = 0;
|
|
||||||
int nbStalled = 0;
|
|
||||||
int nbStalledUploading = 0;
|
|
||||||
int nbStalledDownloading = 0;
|
|
||||||
int nbChecking = 0;
|
|
||||||
int nbErrored = 0;
|
|
||||||
|
|
||||||
const QVector<BitTorrent::Torrent *> torrents = BitTorrent::Session::instance()->torrents();
|
const QVector<BitTorrent::Torrent *> torrents = BitTorrent::Session::instance()->torrents();
|
||||||
for (const BitTorrent::Torrent *torrent : torrents)
|
for (const BitTorrent::Torrent *torrent : torrents)
|
||||||
{
|
{
|
||||||
if (torrent->isDownloading())
|
updateTorrentStatus(torrent);
|
||||||
++nbDownloading;
|
|
||||||
if (torrent->isUploading())
|
|
||||||
++nbSeeding;
|
|
||||||
if (torrent->isCompleted())
|
|
||||||
++nbCompleted;
|
|
||||||
if (torrent->isResumed())
|
|
||||||
++nbResumed;
|
|
||||||
if (torrent->isPaused())
|
|
||||||
++nbPaused;
|
|
||||||
if (torrent->isActive())
|
|
||||||
++nbActive;
|
|
||||||
if (torrent->isInactive())
|
|
||||||
++nbInactive;
|
|
||||||
if (torrent->state() == BitTorrent::TorrentState::StalledUploading)
|
|
||||||
++nbStalledUploading;
|
|
||||||
if (torrent->state() == BitTorrent::TorrentState::StalledDownloading)
|
|
||||||
++nbStalledDownloading;
|
|
||||||
if (torrent->isChecking())
|
|
||||||
++nbChecking;
|
|
||||||
if (torrent->isErrored())
|
|
||||||
++nbErrored;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nbStalled = nbStalledUploading + nbStalledDownloading;
|
updateTexts();
|
||||||
|
}
|
||||||
|
|
||||||
item(TorrentFilter::All)->setData(Qt::DisplayRole, tr("All (%1)").arg(torrents.count()));
|
void StatusFilterWidget::updateTorrentStatus(const BitTorrent::Torrent *torrent)
|
||||||
item(TorrentFilter::Downloading)->setData(Qt::DisplayRole, tr("Downloading (%1)").arg(nbDownloading));
|
{
|
||||||
item(TorrentFilter::Seeding)->setData(Qt::DisplayRole, tr("Seeding (%1)").arg(nbSeeding));
|
const auto update = [this, torrent](const TorrentFilter::Type status, const bool insert, int &count)
|
||||||
item(TorrentFilter::Completed)->setData(Qt::DisplayRole, tr("Completed (%1)").arg(nbCompleted));
|
{
|
||||||
item(TorrentFilter::Resumed)->setData(Qt::DisplayRole, tr("Resumed (%1)").arg(nbResumed));
|
const bool contains = m_torrentsStatus.contains(torrent, status);
|
||||||
item(TorrentFilter::Paused)->setData(Qt::DisplayRole, tr("Paused (%1)").arg(nbPaused));
|
if (insert && !contains)
|
||||||
item(TorrentFilter::Active)->setData(Qt::DisplayRole, tr("Active (%1)").arg(nbActive));
|
{
|
||||||
item(TorrentFilter::Inactive)->setData(Qt::DisplayRole, tr("Inactive (%1)").arg(nbInactive));
|
++count;
|
||||||
item(TorrentFilter::Stalled)->setData(Qt::DisplayRole, tr("Stalled (%1)").arg(nbStalled));
|
m_torrentsStatus.insert(torrent, status);
|
||||||
item(TorrentFilter::StalledUploading)->setData(Qt::DisplayRole, tr("Stalled Uploading (%1)").arg(nbStalledUploading));
|
}
|
||||||
item(TorrentFilter::StalledDownloading)->setData(Qt::DisplayRole, tr("Stalled Downloading (%1)").arg(nbStalledDownloading));
|
else if (!insert && contains)
|
||||||
item(TorrentFilter::Checking)->setData(Qt::DisplayRole, tr("Checking (%1)").arg(nbChecking));
|
{
|
||||||
item(TorrentFilter::Errored)->setData(Qt::DisplayRole, tr("Errored (%1)").arg(nbErrored));
|
--count;
|
||||||
|
m_torrentsStatus.remove(torrent, status);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
update(TorrentFilter::Downloading, torrent->isDownloading(), m_nbDownloading);
|
||||||
|
|
||||||
|
update(TorrentFilter::Seeding, torrent->isUploading(), m_nbSeeding);
|
||||||
|
|
||||||
|
update(TorrentFilter::Completed, torrent->isCompleted(), m_nbCompleted);
|
||||||
|
|
||||||
|
update(TorrentFilter::Resumed, torrent->isResumed(), m_nbResumed);
|
||||||
|
|
||||||
|
update(TorrentFilter::Paused, torrent->isPaused(), m_nbPaused);
|
||||||
|
|
||||||
|
update(TorrentFilter::Active, torrent->isActive(), m_nbActive);
|
||||||
|
|
||||||
|
update(TorrentFilter::Inactive, torrent->isInactive(), m_nbInactive);
|
||||||
|
|
||||||
|
const bool isStalledUploading = (torrent->state() == BitTorrent::TorrentState::StalledUploading);
|
||||||
|
update(TorrentFilter::StalledUploading, isStalledUploading, m_nbStalledUploading);
|
||||||
|
|
||||||
|
const bool isStalledDownloading = (torrent->state() == BitTorrent::TorrentState::StalledDownloading);
|
||||||
|
update(TorrentFilter::StalledDownloading, isStalledDownloading, m_nbStalledDownloading);
|
||||||
|
|
||||||
|
update(TorrentFilter::Checking, torrent->isChecking(), m_nbChecking);
|
||||||
|
|
||||||
|
update(TorrentFilter::Errored, torrent->isErrored(), m_nbErrored);
|
||||||
|
|
||||||
|
m_nbStalled = m_nbStalledUploading + m_nbStalledDownloading;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatusFilterWidget::updateTexts()
|
||||||
|
{
|
||||||
|
const qsizetype torrentsCount = BitTorrent::Session::instance()->torrentsCount();
|
||||||
|
item(TorrentFilter::All)->setData(Qt::DisplayRole, tr("All (%1)").arg(torrentsCount));
|
||||||
|
item(TorrentFilter::Downloading)->setData(Qt::DisplayRole, tr("Downloading (%1)").arg(m_nbDownloading));
|
||||||
|
item(TorrentFilter::Seeding)->setData(Qt::DisplayRole, tr("Seeding (%1)").arg(m_nbSeeding));
|
||||||
|
item(TorrentFilter::Completed)->setData(Qt::DisplayRole, tr("Completed (%1)").arg(m_nbCompleted));
|
||||||
|
item(TorrentFilter::Resumed)->setData(Qt::DisplayRole, tr("Resumed (%1)").arg(m_nbResumed));
|
||||||
|
item(TorrentFilter::Paused)->setData(Qt::DisplayRole, tr("Paused (%1)").arg(m_nbPaused));
|
||||||
|
item(TorrentFilter::Active)->setData(Qt::DisplayRole, tr("Active (%1)").arg(m_nbActive));
|
||||||
|
item(TorrentFilter::Inactive)->setData(Qt::DisplayRole, tr("Inactive (%1)").arg(m_nbInactive));
|
||||||
|
item(TorrentFilter::Stalled)->setData(Qt::DisplayRole, tr("Stalled (%1)").arg(m_nbStalled));
|
||||||
|
item(TorrentFilter::StalledUploading)->setData(Qt::DisplayRole, tr("Stalled Uploading (%1)").arg(m_nbStalledUploading));
|
||||||
|
item(TorrentFilter::StalledDownloading)->setData(Qt::DisplayRole, tr("Stalled Downloading (%1)").arg(m_nbStalledDownloading));
|
||||||
|
item(TorrentFilter::Checking)->setData(Qt::DisplayRole, tr("Checking (%1)").arg(m_nbChecking));
|
||||||
|
item(TorrentFilter::Errored)->setData(Qt::DisplayRole, tr("Errored (%1)").arg(m_nbErrored));
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatusFilterWidget::handleTorrentsUpdated(const QVector<BitTorrent::Torrent *> torrents)
|
||||||
|
{
|
||||||
|
for (const BitTorrent::Torrent *torrent : torrents)
|
||||||
|
updateTorrentStatus(torrent);
|
||||||
|
|
||||||
|
updateTexts();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusFilterWidget::showMenu()
|
void StatusFilterWidget::showMenu()
|
||||||
@ -306,9 +328,64 @@ void StatusFilterWidget::applyFilter(int row)
|
|||||||
transferList->applyStatusFilter(row);
|
transferList->applyStatusFilter(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusFilterWidget::handleNewTorrent(BitTorrent::Torrent *const) {}
|
void StatusFilterWidget::handleNewTorrent(BitTorrent::Torrent *const torrent)
|
||||||
|
{
|
||||||
|
updateTorrentStatus(torrent);
|
||||||
|
updateTexts();
|
||||||
|
}
|
||||||
|
|
||||||
void StatusFilterWidget::torrentAboutToBeDeleted(BitTorrent::Torrent *const) {}
|
void StatusFilterWidget::torrentAboutToBeDeleted(BitTorrent::Torrent *const torrent)
|
||||||
|
{
|
||||||
|
for (const TorrentFilter::Type status : m_torrentsStatus.values(torrent))
|
||||||
|
{
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case TorrentFilter::Downloading:
|
||||||
|
--m_nbDownloading;
|
||||||
|
break;
|
||||||
|
case TorrentFilter::Seeding:
|
||||||
|
--m_nbSeeding;
|
||||||
|
break;
|
||||||
|
case TorrentFilter::Completed:
|
||||||
|
--m_nbCompleted;
|
||||||
|
break;
|
||||||
|
case TorrentFilter::Resumed:
|
||||||
|
--m_nbResumed;
|
||||||
|
break;
|
||||||
|
case TorrentFilter::Paused:
|
||||||
|
--m_nbPaused;
|
||||||
|
break;
|
||||||
|
case TorrentFilter::Active:
|
||||||
|
--m_nbActive;
|
||||||
|
break;
|
||||||
|
case TorrentFilter::Inactive:
|
||||||
|
--m_nbInactive;
|
||||||
|
break;
|
||||||
|
case TorrentFilter::StalledUploading:
|
||||||
|
--m_nbStalledUploading;
|
||||||
|
break;
|
||||||
|
case TorrentFilter::StalledDownloading:
|
||||||
|
--m_nbStalledDownloading;
|
||||||
|
break;
|
||||||
|
case TorrentFilter::Checking:
|
||||||
|
--m_nbChecking;
|
||||||
|
break;
|
||||||
|
case TorrentFilter::Errored:
|
||||||
|
--m_nbErrored;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Q_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_nbStalled = m_nbStalledUploading + m_nbStalledDownloading;
|
||||||
|
|
||||||
|
m_torrentsStatus.remove(torrent);
|
||||||
|
|
||||||
|
updateTexts();
|
||||||
|
}
|
||||||
|
|
||||||
TrackerFiltersList::TrackerFiltersList(QWidget *parent, TransferListWidget *transferList, const bool downloadFavicon)
|
TrackerFiltersList::TrackerFiltersList(QWidget *parent, TransferListWidget *transferList, const bool downloadFavicon)
|
||||||
: BaseFilterWidget(parent, transferList)
|
: BaseFilterWidget(parent, transferList)
|
||||||
@ -342,17 +419,18 @@ TrackerFiltersList::~TrackerFiltersList()
|
|||||||
void TrackerFiltersList::addItem(const QString &tracker, const BitTorrent::TorrentID &id)
|
void TrackerFiltersList::addItem(const QString &tracker, const BitTorrent::TorrentID &id)
|
||||||
{
|
{
|
||||||
const QString host {getHost(tracker)};
|
const QString host {getHost(tracker)};
|
||||||
const bool exists {m_trackers.contains(host)};
|
const auto existingDataItr = m_trackers.find(host);
|
||||||
|
const bool exists {existingDataItr != m_trackers.end()};
|
||||||
QListWidgetItem *trackerItem {nullptr};
|
QListWidgetItem *trackerItem {nullptr};
|
||||||
|
|
||||||
if (exists)
|
if (exists)
|
||||||
{
|
{
|
||||||
if (m_trackers.value(host).contains(id))
|
if (existingDataItr->torrents.contains(id))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
trackerItem = item((host == NULL_HOST)
|
trackerItem = (host == NULL_HOST)
|
||||||
? TRACKERLESS_ROW
|
? item(TRACKERLESS_ROW)
|
||||||
: rowFromTracker(host));
|
: existingDataItr->item;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -364,7 +442,7 @@ void TrackerFiltersList::addItem(const QString &tracker, const BitTorrent::Torre
|
|||||||
}
|
}
|
||||||
if (!trackerItem) return;
|
if (!trackerItem) return;
|
||||||
|
|
||||||
QSet<BitTorrent::TorrentID> &torrentIDs {m_trackers[host]};
|
QSet<BitTorrent::TorrentID> &torrentIDs {m_trackers[host].torrents};
|
||||||
torrentIDs.insert(id);
|
torrentIDs.insert(id);
|
||||||
|
|
||||||
if (host == NULL_HOST)
|
if (host == NULL_HOST)
|
||||||
@ -378,7 +456,7 @@ void TrackerFiltersList::addItem(const QString &tracker, const BitTorrent::Torre
|
|||||||
trackerItem->setText(QString::fromLatin1("%1 (%2)").arg(host, QString::number(torrentIDs.size())));
|
trackerItem->setText(QString::fromLatin1("%1 (%2)").arg(host, QString::number(torrentIDs.size())));
|
||||||
if (exists)
|
if (exists)
|
||||||
{
|
{
|
||||||
if (currentRow() == rowFromTracker(host))
|
if (trackerFromRow(currentRow()) == host)
|
||||||
applyFilter(currentRow());
|
applyFilter(currentRow());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -401,13 +479,12 @@ void TrackerFiltersList::addItem(const QString &tracker, const BitTorrent::Torre
|
|||||||
void TrackerFiltersList::removeItem(const QString &trackerURL, const BitTorrent::TorrentID &id)
|
void TrackerFiltersList::removeItem(const QString &trackerURL, const BitTorrent::TorrentID &id)
|
||||||
{
|
{
|
||||||
const QString host = getHost(trackerURL);
|
const QString host = getHost(trackerURL);
|
||||||
QSet<BitTorrent::TorrentID> torrentIDs = m_trackers.value(host);
|
QSet<BitTorrent::TorrentID> torrentIDs = m_trackers.value(host).torrents;
|
||||||
if (torrentIDs.empty())
|
if (torrentIDs.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
torrentIDs.remove(id);
|
torrentIDs.remove(id);
|
||||||
|
|
||||||
int row = 0;
|
|
||||||
QListWidgetItem *trackerItem = nullptr;
|
QListWidgetItem *trackerItem = nullptr;
|
||||||
|
|
||||||
if (!host.isEmpty())
|
if (!host.isEmpty())
|
||||||
@ -441,12 +518,11 @@ void TrackerFiltersList::removeItem(const QString &trackerURL, const BitTorrent:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
row = rowFromTracker(host);
|
trackerItem = m_trackers.value(host).item;
|
||||||
trackerItem = item(row);
|
|
||||||
|
|
||||||
if (torrentIDs.empty())
|
if (torrentIDs.empty())
|
||||||
{
|
{
|
||||||
if (currentRow() == row)
|
if (currentItem() == trackerItem)
|
||||||
setCurrentRow(0, QItemSelectionModel::SelectCurrent);
|
setCurrentRow(0, QItemSelectionModel::SelectCurrent);
|
||||||
delete trackerItem;
|
delete trackerItem;
|
||||||
m_trackers.remove(host);
|
m_trackers.remove(host);
|
||||||
@ -459,15 +535,14 @@ void TrackerFiltersList::removeItem(const QString &trackerURL, const BitTorrent:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
row = 1;
|
|
||||||
trackerItem = item(TRACKERLESS_ROW);
|
trackerItem = item(TRACKERLESS_ROW);
|
||||||
trackerItem->setText(tr("Trackerless (%1)").arg(torrentIDs.size()));
|
trackerItem->setText(tr("Trackerless (%1)").arg(torrentIDs.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_trackers.insert(host, torrentIDs);
|
m_trackers.insert(host, {torrentIDs, trackerItem});
|
||||||
|
|
||||||
if (currentRow() == row)
|
if (currentItem() == trackerItem)
|
||||||
applyFilter(row);
|
applyFilter(currentRow());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackerFiltersList::changeTrackerless(const bool trackerless, const BitTorrent::TorrentID &id)
|
void TrackerFiltersList::changeTrackerless(const bool trackerless, const BitTorrent::TorrentID &id)
|
||||||
@ -630,12 +705,12 @@ void TrackerFiltersList::applyFilter(const int row)
|
|||||||
void TrackerFiltersList::handleNewTorrent(BitTorrent::Torrent *const torrent)
|
void TrackerFiltersList::handleNewTorrent(BitTorrent::Torrent *const torrent)
|
||||||
{
|
{
|
||||||
const BitTorrent::TorrentID torrentID {torrent->id()};
|
const BitTorrent::TorrentID torrentID {torrent->id()};
|
||||||
const QVector<BitTorrent::TrackerEntry> trackers {torrent->trackers()};
|
const QVector<QString> trackerURLs {torrent->trackerURLs()};
|
||||||
for (const BitTorrent::TrackerEntry &tracker : trackers)
|
for (const QString &trackerURL : trackerURLs)
|
||||||
addItem(tracker.url, torrentID);
|
addItem(trackerURL, torrentID);
|
||||||
|
|
||||||
// Check for trackerless torrent
|
// Check for trackerless torrent
|
||||||
if (trackers.isEmpty())
|
if (trackerURLs.isEmpty())
|
||||||
addItem(NULL_HOST, torrentID);
|
addItem(NULL_HOST, torrentID);
|
||||||
|
|
||||||
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));
|
||||||
@ -644,12 +719,12 @@ void TrackerFiltersList::handleNewTorrent(BitTorrent::Torrent *const torrent)
|
|||||||
void TrackerFiltersList::torrentAboutToBeDeleted(BitTorrent::Torrent *const torrent)
|
void TrackerFiltersList::torrentAboutToBeDeleted(BitTorrent::Torrent *const torrent)
|
||||||
{
|
{
|
||||||
const BitTorrent::TorrentID torrentID {torrent->id()};
|
const BitTorrent::TorrentID torrentID {torrent->id()};
|
||||||
const QVector<BitTorrent::TrackerEntry> trackers {torrent->trackers()};
|
const QVector<QString> trackerURLs {torrent->trackerURLs()};
|
||||||
for (const BitTorrent::TrackerEntry &tracker : trackers)
|
for (const QString &trackerURL : trackerURLs)
|
||||||
removeItem(tracker.url, torrentID);
|
removeItem(trackerURL, torrentID);
|
||||||
|
|
||||||
// Check for trackerless torrent
|
// Check for trackerless torrent
|
||||||
if (trackers.isEmpty())
|
if (trackerURLs.isEmpty())
|
||||||
removeItem(NULL_HOST, torrentID);
|
removeItem(NULL_HOST, torrentID);
|
||||||
|
|
||||||
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));
|
||||||
@ -681,13 +756,13 @@ QSet<BitTorrent::TorrentID> TrackerFiltersList::getTorrentIDs(const int row) con
|
|||||||
switch (row)
|
switch (row)
|
||||||
{
|
{
|
||||||
case TRACKERLESS_ROW:
|
case TRACKERLESS_ROW:
|
||||||
return m_trackers.value(NULL_HOST);
|
return m_trackers.value(NULL_HOST).torrents;
|
||||||
case ERROR_ROW:
|
case ERROR_ROW:
|
||||||
return {m_errors.keyBegin(), m_errors.keyEnd()};
|
return {m_errors.keyBegin(), m_errors.keyEnd()};
|
||||||
case WARNING_ROW:
|
case WARNING_ROW:
|
||||||
return {m_warnings.keyBegin(), m_warnings.keyEnd()};
|
return {m_warnings.keyBegin(), m_warnings.keyEnd()};
|
||||||
default:
|
default:
|
||||||
return m_trackers.value(trackerFromRow(row));
|
return m_trackers.value(trackerFromRow(row)).torrents;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "base/bittorrent/infohash.h"
|
#include "base/bittorrent/infohash.h"
|
||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/bittorrent/trackerentry.h"
|
#include "base/bittorrent/trackerentry.h"
|
||||||
|
#include "base/torrentfilter.h"
|
||||||
#include "base/path.h"
|
#include "base/path.h"
|
||||||
|
|
||||||
class QCheckBox;
|
class QCheckBox;
|
||||||
@ -81,7 +82,7 @@ public:
|
|||||||
~StatusFilterWidget() override;
|
~StatusFilterWidget() override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void updateTorrentNumbers();
|
void handleTorrentsUpdated(const QVector<BitTorrent::Torrent *> torrents);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// These 4 methods are virtual slots in the base class.
|
// These 4 methods are virtual slots in the base class.
|
||||||
@ -90,6 +91,24 @@ private:
|
|||||||
void applyFilter(int row) override;
|
void applyFilter(int row) override;
|
||||||
void handleNewTorrent(BitTorrent::Torrent *const) override;
|
void handleNewTorrent(BitTorrent::Torrent *const) override;
|
||||||
void torrentAboutToBeDeleted(BitTorrent::Torrent *const) override;
|
void torrentAboutToBeDeleted(BitTorrent::Torrent *const) override;
|
||||||
|
|
||||||
|
void populate();
|
||||||
|
void updateTorrentStatus(const BitTorrent::Torrent *torrent);
|
||||||
|
void updateTexts();
|
||||||
|
|
||||||
|
QMultiHash<const BitTorrent::Torrent *, TorrentFilter::Type> m_torrentsStatus;
|
||||||
|
int m_nbDownloading = 0;
|
||||||
|
int m_nbSeeding = 0;
|
||||||
|
int m_nbCompleted = 0;
|
||||||
|
int m_nbResumed = 0;
|
||||||
|
int m_nbPaused = 0;
|
||||||
|
int m_nbActive = 0;
|
||||||
|
int m_nbInactive = 0;
|
||||||
|
int m_nbStalled = 0;
|
||||||
|
int m_nbStalledUploading = 0;
|
||||||
|
int m_nbStalledDownloading = 0;
|
||||||
|
int m_nbChecking = 0;
|
||||||
|
int m_nbErrored = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TrackerFiltersList final : public BaseFilterWidget
|
class TrackerFiltersList final : public BaseFilterWidget
|
||||||
@ -123,7 +142,13 @@ private:
|
|||||||
QSet<BitTorrent::TorrentID> getTorrentIDs(int row) const;
|
QSet<BitTorrent::TorrentID> getTorrentIDs(int row) const;
|
||||||
void downloadFavicon(const QString &url);
|
void downloadFavicon(const QString &url);
|
||||||
|
|
||||||
QHash<QString, QSet<BitTorrent::TorrentID>> m_trackers; // <tracker host, torrent IDs>
|
struct TrackerData
|
||||||
|
{
|
||||||
|
QSet<BitTorrent::TorrentID> torrents;
|
||||||
|
QListWidgetItem *item = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
QHash<QString, TrackerData> m_trackers;
|
||||||
QHash<BitTorrent::TorrentID, QSet<QString>> m_errors; // <torrent ID, tracker hosts>
|
QHash<BitTorrent::TorrentID, QSet<QString>> m_errors; // <torrent ID, tracker hosts>
|
||||||
QHash<BitTorrent::TorrentID, QSet<QString>> m_warnings; // <torrent ID, tracker hosts>
|
QHash<BitTorrent::TorrentID, QSet<QString>> m_warnings; // <torrent ID, tracker hosts>
|
||||||
PathList m_iconPaths;
|
PathList m_iconPaths;
|
||||||
|
Loading…
Reference in New Issue
Block a user