mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-20 15:37:26 -06:00
@@ -1386,7 +1386,7 @@ void MainWindow::showFiltersSidebar(const bool show)
|
||||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackersAdded, m_transferListFiltersWidget, &TransferListFiltersWidget::addTrackers);
|
||||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackersRemoved, m_transferListFiltersWidget, &TransferListFiltersWidget::removeTrackers);
|
||||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackersChanged, m_transferListFiltersWidget, &TransferListFiltersWidget::refreshTrackers);
|
||||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerEntriesUpdated, m_transferListFiltersWidget, &TransferListFiltersWidget::trackerEntriesUpdated);
|
||||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerEntryStatusesUpdated, m_transferListFiltersWidget, &TransferListFiltersWidget::trackerEntryStatusesUpdated);
|
||||
|
||||
m_splitter->insertWidget(0, m_transferListFiltersWidget);
|
||||
m_splitter->setCollapsible(0, true);
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "base/bittorrent/peerinfo.h"
|
||||
#include "base/bittorrent/session.h"
|
||||
#include "base/bittorrent/torrent.h"
|
||||
#include "base/bittorrent/trackerentry.h"
|
||||
#include "base/global.h"
|
||||
#include "base/utils/misc.h"
|
||||
|
||||
@@ -68,24 +69,24 @@ namespace
|
||||
return (val > -1) ? QString::number(val) : TrackerListModel::tr("N/A");
|
||||
}
|
||||
|
||||
QString toString(const BitTorrent::TrackerEntryStatus status)
|
||||
QString toString(const BitTorrent::TrackerEndpointState state)
|
||||
{
|
||||
switch (status)
|
||||
switch (state)
|
||||
{
|
||||
case BitTorrent::TrackerEntryStatus::Working:
|
||||
case BitTorrent::TrackerEndpointState::Working:
|
||||
return TrackerListModel::tr(STR_WORKING);
|
||||
case BitTorrent::TrackerEntryStatus::Updating:
|
||||
case BitTorrent::TrackerEndpointState::Updating:
|
||||
return TrackerListModel::tr("Updating...");
|
||||
case BitTorrent::TrackerEntryStatus::NotWorking:
|
||||
case BitTorrent::TrackerEndpointState::NotWorking:
|
||||
return TrackerListModel::tr("Not working");
|
||||
case BitTorrent::TrackerEntryStatus::TrackerError:
|
||||
case BitTorrent::TrackerEndpointState::TrackerError:
|
||||
return TrackerListModel::tr("Tracker error");
|
||||
case BitTorrent::TrackerEntryStatus::Unreachable:
|
||||
case BitTorrent::TrackerEndpointState::Unreachable:
|
||||
return TrackerListModel::tr("Unreachable");
|
||||
case BitTorrent::TrackerEntryStatus::NotContacted:
|
||||
case BitTorrent::TrackerEndpointState::NotContacted:
|
||||
return TrackerListModel::tr("Not contacted yet");
|
||||
}
|
||||
return TrackerListModel::tr("Invalid status!");
|
||||
return TrackerListModel::tr("Invalid state!");
|
||||
}
|
||||
|
||||
QString statusDHT(const BitTorrent::Torrent *torrent)
|
||||
@@ -132,7 +133,7 @@ struct TrackerListModel::Item final
|
||||
QString name {};
|
||||
int tier = -1;
|
||||
int btVersion = -1;
|
||||
BitTorrent::TrackerEntryStatus status = BitTorrent::TrackerEntryStatus::NotContacted;
|
||||
BitTorrent::TrackerEndpointState status = BitTorrent::TrackerEndpointState::NotContacted;
|
||||
QString message {};
|
||||
|
||||
int numPeers = -1;
|
||||
@@ -159,11 +160,11 @@ struct TrackerListModel::Item final
|
||||
>> childItems {};
|
||||
|
||||
Item(QStringView name, QStringView message);
|
||||
explicit Item(const BitTorrent::TrackerEntry &trackerEntry);
|
||||
Item(const std::shared_ptr<Item> &parentItem, const BitTorrent::TrackerEndpointEntry &endpointEntry);
|
||||
explicit Item(const BitTorrent::TrackerEntryStatus &trackerEntryStatus);
|
||||
Item(const std::shared_ptr<Item> &parentItem, const BitTorrent::TrackerEndpointStatus &endpointStatus);
|
||||
|
||||
void fillFrom(const BitTorrent::TrackerEntry &trackerEntry);
|
||||
void fillFrom(const BitTorrent::TrackerEndpointEntry &endpointEntry);
|
||||
void fillFrom(const BitTorrent::TrackerEntryStatus &trackerEntryStatus);
|
||||
void fillFrom(const BitTorrent::TrackerEndpointStatus &endpointStatus);
|
||||
};
|
||||
|
||||
class TrackerListModel::Items final : public multi_index_container<
|
||||
@@ -180,53 +181,53 @@ TrackerListModel::Item::Item(const QStringView name, const QStringView message)
|
||||
{
|
||||
}
|
||||
|
||||
TrackerListModel::Item::Item(const BitTorrent::TrackerEntry &trackerEntry)
|
||||
: name {trackerEntry.url}
|
||||
TrackerListModel::Item::Item(const BitTorrent::TrackerEntryStatus &trackerEntryStatus)
|
||||
: name {trackerEntryStatus.url}
|
||||
{
|
||||
fillFrom(trackerEntry);
|
||||
fillFrom(trackerEntryStatus);
|
||||
}
|
||||
|
||||
TrackerListModel::Item::Item(const std::shared_ptr<Item> &parentItem, const BitTorrent::TrackerEndpointEntry &endpointEntry)
|
||||
: name {endpointEntry.name}
|
||||
, btVersion {endpointEntry.btVersion}
|
||||
TrackerListModel::Item::Item(const std::shared_ptr<Item> &parentItem, const BitTorrent::TrackerEndpointStatus &endpointStatus)
|
||||
: name {endpointStatus.name}
|
||||
, btVersion {endpointStatus.btVersion}
|
||||
, parentItem {parentItem}
|
||||
{
|
||||
fillFrom(endpointEntry);
|
||||
fillFrom(endpointStatus);
|
||||
}
|
||||
|
||||
void TrackerListModel::Item::fillFrom(const BitTorrent::TrackerEntry &trackerEntry)
|
||||
void TrackerListModel::Item::fillFrom(const BitTorrent::TrackerEntryStatus &trackerEntryStatus)
|
||||
{
|
||||
Q_ASSERT(parentItem.expired());
|
||||
Q_ASSERT(trackerEntry.url == name);
|
||||
Q_ASSERT(trackerEntryStatus.url == name);
|
||||
|
||||
tier = trackerEntry.tier;
|
||||
status = trackerEntry.status;
|
||||
message = trackerEntry.message;
|
||||
numPeers = trackerEntry.numPeers;
|
||||
numSeeds = trackerEntry.numSeeds;
|
||||
numLeeches = trackerEntry.numLeeches;
|
||||
numDownloaded = trackerEntry.numDownloaded;
|
||||
nextAnnounceTime = trackerEntry.nextAnnounceTime;
|
||||
minAnnounceTime = trackerEntry.minAnnounceTime;
|
||||
tier = trackerEntryStatus.tier;
|
||||
status = trackerEntryStatus.state;
|
||||
message = trackerEntryStatus.message;
|
||||
numPeers = trackerEntryStatus.numPeers;
|
||||
numSeeds = trackerEntryStatus.numSeeds;
|
||||
numLeeches = trackerEntryStatus.numLeeches;
|
||||
numDownloaded = trackerEntryStatus.numDownloaded;
|
||||
nextAnnounceTime = trackerEntryStatus.nextAnnounceTime;
|
||||
minAnnounceTime = trackerEntryStatus.minAnnounceTime;
|
||||
secsToNextAnnounce = 0;
|
||||
secsToMinAnnounce = 0;
|
||||
announceTimestamp = QDateTime();
|
||||
}
|
||||
|
||||
void TrackerListModel::Item::fillFrom(const BitTorrent::TrackerEndpointEntry &endpointEntry)
|
||||
void TrackerListModel::Item::fillFrom(const BitTorrent::TrackerEndpointStatus &endpointStatus)
|
||||
{
|
||||
Q_ASSERT(!parentItem.expired());
|
||||
Q_ASSERT(endpointEntry.name == name);
|
||||
Q_ASSERT(endpointEntry.btVersion == btVersion);
|
||||
Q_ASSERT(endpointStatus.name == name);
|
||||
Q_ASSERT(endpointStatus.btVersion == btVersion);
|
||||
|
||||
status = endpointEntry.status;
|
||||
message = endpointEntry.message;
|
||||
numPeers = endpointEntry.numPeers;
|
||||
numSeeds = endpointEntry.numSeeds;
|
||||
numLeeches = endpointEntry.numLeeches;
|
||||
numDownloaded = endpointEntry.numDownloaded;
|
||||
nextAnnounceTime = endpointEntry.nextAnnounceTime;
|
||||
minAnnounceTime = endpointEntry.minAnnounceTime;
|
||||
status = endpointStatus.state;
|
||||
message = endpointStatus.message;
|
||||
numPeers = endpointStatus.numPeers;
|
||||
numSeeds = endpointStatus.numSeeds;
|
||||
numLeeches = endpointStatus.numLeeches;
|
||||
numDownloaded = endpointStatus.numDownloaded;
|
||||
nextAnnounceTime = endpointStatus.nextAnnounceTime;
|
||||
minAnnounceTime = endpointStatus.minAnnounceTime;
|
||||
secsToNextAnnounce = 0;
|
||||
secsToMinAnnounce = 0;
|
||||
announceTimestamp = QDateTime();
|
||||
@@ -261,8 +262,8 @@ TrackerListModel::TrackerListModel(BitTorrent::Session *btSession, QObject *pare
|
||||
if (torrent == m_torrent)
|
||||
onTrackersChanged();
|
||||
});
|
||||
connect(m_btSession, &BitTorrent::Session::trackerEntriesUpdated, this
|
||||
, [this](BitTorrent::Torrent *torrent, const QHash<QString, BitTorrent::TrackerEntry> &updatedTrackers)
|
||||
connect(m_btSession, &BitTorrent::Session::trackerEntryStatusesUpdated, this
|
||||
, [this](BitTorrent::Torrent *torrent, const QHash<QString, BitTorrent::TrackerEntryStatus> &updatedTrackers)
|
||||
{
|
||||
if (torrent == m_torrent)
|
||||
onTrackersUpdated(updatedTrackers);
|
||||
@@ -296,8 +297,8 @@ void TrackerListModel::populate()
|
||||
{
|
||||
Q_ASSERT(m_torrent);
|
||||
|
||||
const QList<BitTorrent::TrackerEntry> trackerEntries = m_torrent->trackers();
|
||||
m_items->reserve(trackerEntries.size() + STICKY_ROW_COUNT);
|
||||
const QList<BitTorrent::TrackerEntryStatus> trackers = m_torrent->trackers();
|
||||
m_items->reserve(trackers.size() + STICKY_ROW_COUNT);
|
||||
|
||||
const QString &privateTorrentMessage = m_torrent->isPrivate() ? tr(STR_PRIVATE_MSG) : u""_s;
|
||||
m_items->emplace_back(std::make_shared<Item>(u"** [DHT] **", privateTorrentMessage));
|
||||
@@ -365,46 +366,44 @@ void TrackerListModel::populate()
|
||||
emit dataChanged(index(ROW_DHT, COL_SEEDS), index(ROW_LSD, COL_LEECHES));
|
||||
});
|
||||
|
||||
for (const BitTorrent::TrackerEntry &trackerEntry : trackerEntries)
|
||||
addTrackerItem(trackerEntry);
|
||||
for (const BitTorrent::TrackerEntryStatus &status : trackers)
|
||||
addTrackerItem(status);
|
||||
|
||||
m_announceTimestamp = QDateTime::currentDateTime();
|
||||
m_announceRefreshTimer->start(ANNOUNCE_TIME_REFRESH_INTERVAL);
|
||||
}
|
||||
|
||||
std::shared_ptr<TrackerListModel::Item> TrackerListModel::createTrackerItem(const BitTorrent::TrackerEntry &trackerEntry)
|
||||
std::shared_ptr<TrackerListModel::Item> TrackerListModel::createTrackerItem(const BitTorrent::TrackerEntryStatus &trackerEntryStatus)
|
||||
{
|
||||
auto item = std::make_shared<Item>(trackerEntry);
|
||||
for (const auto &[id, endpointEntry] : trackerEntry.endpointEntries.asKeyValueRange())
|
||||
{
|
||||
item->childItems.emplace_back(std::make_shared<Item>(item, endpointEntry));
|
||||
}
|
||||
const auto item = std::make_shared<Item>(trackerEntryStatus);
|
||||
for (const auto &[id, endpointStatus] : trackerEntryStatus.endpoints.asKeyValueRange())
|
||||
item->childItems.emplace_back(std::make_shared<Item>(item, endpointStatus));
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
void TrackerListModel::addTrackerItem(const BitTorrent::TrackerEntry &trackerEntry)
|
||||
void TrackerListModel::addTrackerItem(const BitTorrent::TrackerEntryStatus &trackerEntryStatus)
|
||||
{
|
||||
[[maybe_unused]] const auto &[iter, res] = m_items->emplace_back(createTrackerItem(trackerEntry));
|
||||
[[maybe_unused]] const auto &[iter, res] = m_items->emplace_back(createTrackerItem(trackerEntryStatus));
|
||||
Q_ASSERT(res);
|
||||
}
|
||||
|
||||
void TrackerListModel::updateTrackerItem(const std::shared_ptr<Item> &item, const BitTorrent::TrackerEntry &trackerEntry)
|
||||
void TrackerListModel::updateTrackerItem(const std::shared_ptr<Item> &item, const BitTorrent::TrackerEntryStatus &trackerEntryStatus)
|
||||
{
|
||||
QSet<std::pair<QString, int>> endpointItemIDs;
|
||||
QList<std::shared_ptr<Item>> newEndpointItems;
|
||||
for (const auto &[id, endpointEntry] : trackerEntry.endpointEntries.asKeyValueRange())
|
||||
for (const auto &[id, endpointStatus] : trackerEntryStatus.endpoints.asKeyValueRange())
|
||||
{
|
||||
endpointItemIDs.insert(id);
|
||||
|
||||
auto &itemsByID = item->childItems.get<ByID>();
|
||||
if (const auto &iter = itemsByID.find(std::make_tuple(id.first, id.second)); iter != itemsByID.end())
|
||||
{
|
||||
(*iter)->fillFrom(endpointEntry);
|
||||
(*iter)->fillFrom(endpointStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
newEndpointItems.emplace_back(std::make_shared<Item>(item, endpointEntry));
|
||||
newEndpointItems.emplace_back(std::make_shared<Item>(item, endpointStatus));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,7 +428,7 @@ void TrackerListModel::updateTrackerItem(const std::shared_ptr<Item> &item, cons
|
||||
}
|
||||
}
|
||||
|
||||
const auto numRows = rowCount(trackerIndex);
|
||||
const int numRows = rowCount(trackerIndex);
|
||||
emit dataChanged(index(0, 0, trackerIndex), index((numRows - 1), (columnCount(trackerIndex) - 1), trackerIndex));
|
||||
|
||||
if (!newEndpointItems.isEmpty())
|
||||
@@ -440,7 +439,7 @@ void TrackerListModel::updateTrackerItem(const std::shared_ptr<Item> &item, cons
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
item->fillFrom(trackerEntry);
|
||||
item->fillFrom(trackerEntryStatus);
|
||||
emit dataChanged(trackerIndex, index(trackerRow, (columnCount() - 1)));
|
||||
}
|
||||
|
||||
@@ -697,10 +696,10 @@ QModelIndex TrackerListModel::parent(const QModelIndex &index) const
|
||||
|
||||
void TrackerListModel::onTrackersAdded(const QList<BitTorrent::TrackerEntry> &newTrackers)
|
||||
{
|
||||
const auto row = rowCount();
|
||||
const int row = rowCount();
|
||||
beginInsertRows({}, row, (row + newTrackers.size() - 1));
|
||||
for (const BitTorrent::TrackerEntry &trackerEntry : newTrackers)
|
||||
addTrackerItem(trackerEntry);
|
||||
for (const BitTorrent::TrackerEntry &entry : newTrackers)
|
||||
addTrackerItem({entry.url, entry.tier});
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
@@ -727,18 +726,18 @@ void TrackerListModel::onTrackersChanged()
|
||||
trackerItemIDs.insert(m_items->at(i)->name);
|
||||
|
||||
QList<std::shared_ptr<Item>> newTrackerItems;
|
||||
for (const BitTorrent::TrackerEntry &trackerEntry : m_torrent->trackers())
|
||||
for (const BitTorrent::TrackerEntryStatus &trackerEntryStatus : m_torrent->trackers())
|
||||
{
|
||||
trackerItemIDs.insert(trackerEntry.url);
|
||||
trackerItemIDs.insert(trackerEntryStatus.url);
|
||||
|
||||
auto &itemsByName = m_items->get<ByName>();
|
||||
if (const auto &iter = itemsByName.find(trackerEntry.url); iter != itemsByName.end())
|
||||
if (const auto &iter = itemsByName.find(trackerEntryStatus.url); iter != itemsByName.end())
|
||||
{
|
||||
updateTrackerItem(*iter, trackerEntry);
|
||||
updateTrackerItem(*iter, trackerEntryStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
newTrackerItems.emplace_back(createTrackerItem(trackerEntry));
|
||||
newTrackerItems.emplace_back(createTrackerItem(trackerEntryStatus));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -760,7 +759,7 @@ void TrackerListModel::onTrackersChanged()
|
||||
|
||||
if (!newTrackerItems.isEmpty())
|
||||
{
|
||||
const auto numRows = rowCount();
|
||||
const int numRows = rowCount();
|
||||
beginInsertRows({}, numRows, (numRows + newTrackerItems.size() - 1));
|
||||
for (const auto &newTrackerItem : asConst(newTrackerItems))
|
||||
m_items->get<0>().push_back(newTrackerItem);
|
||||
@@ -768,14 +767,14 @@ void TrackerListModel::onTrackersChanged()
|
||||
}
|
||||
}
|
||||
|
||||
void TrackerListModel::onTrackersUpdated(const QHash<QString, BitTorrent::TrackerEntry> &updatedTrackers)
|
||||
void TrackerListModel::onTrackersUpdated(const QHash<QString, BitTorrent::TrackerEntryStatus> &updatedTrackers)
|
||||
{
|
||||
for (const auto &[url, entry] : updatedTrackers.asKeyValueRange())
|
||||
for (const auto &[url, tracker] : updatedTrackers.asKeyValueRange())
|
||||
{
|
||||
auto &itemsByName = m_items->get<ByName>();
|
||||
if (const auto &iter = itemsByName.find(entry.url); iter != itemsByName.end()) [[likely]]
|
||||
if (const auto &iter = itemsByName.find(tracker.url); iter != itemsByName.end()) [[likely]]
|
||||
{
|
||||
updateTrackerItem(*iter, entry);
|
||||
updateTrackerItem(*iter, tracker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <QAbstractItemModel>
|
||||
#include <QDateTime>
|
||||
|
||||
#include "base/bittorrent/trackerentry.h"
|
||||
#include "base/bittorrent/trackerentrystatus.h"
|
||||
|
||||
class QTimer;
|
||||
|
||||
@@ -43,6 +43,7 @@ namespace BitTorrent
|
||||
{
|
||||
class Session;
|
||||
class Torrent;
|
||||
struct TrackerEntry;
|
||||
}
|
||||
|
||||
class TrackerListModel final : public QAbstractItemModel
|
||||
@@ -99,14 +100,14 @@ private:
|
||||
struct Item;
|
||||
|
||||
void populate();
|
||||
std::shared_ptr<Item> createTrackerItem(const BitTorrent::TrackerEntry &trackerEntry);
|
||||
void addTrackerItem(const BitTorrent::TrackerEntry &trackerEntry);
|
||||
void updateTrackerItem(const std::shared_ptr<Item> &item, const BitTorrent::TrackerEntry &trackerEntry);
|
||||
std::shared_ptr<Item> createTrackerItem(const BitTorrent::TrackerEntryStatus &trackerEntryStatus);
|
||||
void addTrackerItem(const BitTorrent::TrackerEntryStatus &trackerEntryStatus);
|
||||
void updateTrackerItem(const std::shared_ptr<Item> &item, const BitTorrent::TrackerEntryStatus &trackerEntryStatus);
|
||||
void refreshAnnounceTimes();
|
||||
void onTrackersAdded(const QList<BitTorrent::TrackerEntry> &newTrackers);
|
||||
void onTrackersRemoved(const QStringList &deletedTrackers);
|
||||
void onTrackersChanged();
|
||||
void onTrackersUpdated(const QHash<QString, BitTorrent::TrackerEntry> &updatedTrackers);
|
||||
void onTrackersUpdated(const QHash<QString, BitTorrent::TrackerEntryStatus> &updatedTrackers);
|
||||
|
||||
BitTorrent::Session *m_btSession = nullptr;
|
||||
BitTorrent::Torrent *m_torrent = nullptr;
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
#include "base/bittorrent/session.h"
|
||||
#include "base/bittorrent/torrent.h"
|
||||
#include "base/bittorrent/trackerentry.h"
|
||||
#include "base/bittorrent/trackerentrystatus.h"
|
||||
#include "base/global.h"
|
||||
#include "base/preferences.h"
|
||||
#include "gui/autoexpandabledialog.h"
|
||||
@@ -142,52 +142,68 @@ QModelIndexList TrackerListWidget::getSelectedTrackerRows() const
|
||||
|
||||
void TrackerListWidget::decreaseSelectedTrackerTiers()
|
||||
{
|
||||
const auto &trackerIndexes = getSelectedTrackerRows();
|
||||
const QModelIndexList trackerIndexes = getSelectedTrackerRows();
|
||||
if (trackerIndexes.isEmpty())
|
||||
return;
|
||||
|
||||
QSet<QString> trackerURLs;
|
||||
trackerURLs.reserve(trackerIndexes.size());
|
||||
for (const QModelIndex &index : trackerIndexes)
|
||||
{
|
||||
trackerURLs.insert(index.siblingAtColumn(TrackerListModel::COL_URL).data().toString());
|
||||
}
|
||||
|
||||
QList<BitTorrent::TrackerEntry> trackers = m_model->torrent()->trackers();
|
||||
for (BitTorrent::TrackerEntry &trackerEntry : trackers)
|
||||
const QList<BitTorrent::TrackerEntryStatus> trackers = m_model->torrent()->trackers();
|
||||
QList<BitTorrent::TrackerEntry> adjustedTrackers;
|
||||
adjustedTrackers.reserve(trackers.size());
|
||||
|
||||
for (const BitTorrent::TrackerEntryStatus &status : trackers)
|
||||
{
|
||||
if (trackerURLs.contains(trackerEntry.url))
|
||||
BitTorrent::TrackerEntry entry
|
||||
{
|
||||
if (trackerEntry.tier > 0)
|
||||
--trackerEntry.tier;
|
||||
.url = status.url,
|
||||
.tier = status.tier
|
||||
};
|
||||
if (trackerURLs.contains(entry.url))
|
||||
{
|
||||
if (entry.tier > 0)
|
||||
--entry.tier;
|
||||
}
|
||||
adjustedTrackers.append(entry);
|
||||
}
|
||||
|
||||
m_model->torrent()->replaceTrackers(trackers);
|
||||
m_model->torrent()->replaceTrackers(adjustedTrackers);
|
||||
}
|
||||
|
||||
void TrackerListWidget::increaseSelectedTrackerTiers()
|
||||
{
|
||||
const auto &trackerIndexes = getSelectedTrackerRows();
|
||||
const QModelIndexList trackerIndexes = getSelectedTrackerRows();
|
||||
if (trackerIndexes.isEmpty())
|
||||
return;
|
||||
|
||||
QSet<QString> trackerURLs;
|
||||
trackerURLs.reserve(trackerIndexes.size());
|
||||
for (const QModelIndex &index : trackerIndexes)
|
||||
{
|
||||
trackerURLs.insert(index.siblingAtColumn(TrackerListModel::COL_URL).data().toString());
|
||||
}
|
||||
|
||||
QList<BitTorrent::TrackerEntry> trackers = m_model->torrent()->trackers();
|
||||
for (BitTorrent::TrackerEntry &trackerEntry : trackers)
|
||||
const QList<BitTorrent::TrackerEntryStatus> trackers = m_model->torrent()->trackers();
|
||||
QList<BitTorrent::TrackerEntry> adjustedTrackers;
|
||||
adjustedTrackers.reserve(trackers.size());
|
||||
|
||||
for (const BitTorrent::TrackerEntryStatus &status : trackers)
|
||||
{
|
||||
if (trackerURLs.contains(trackerEntry.url))
|
||||
BitTorrent::TrackerEntry entry
|
||||
{
|
||||
if (trackerEntry.tier < std::numeric_limits<decltype(trackerEntry.tier)>::max())
|
||||
++trackerEntry.tier;
|
||||
.url = status.url,
|
||||
.tier = status.tier
|
||||
};
|
||||
if (trackerURLs.contains(entry.url))
|
||||
{
|
||||
if (entry.tier < std::numeric_limits<decltype(entry.tier)>::max())
|
||||
++entry.tier;
|
||||
}
|
||||
adjustedTrackers.append(entry);
|
||||
}
|
||||
|
||||
m_model->torrent()->replaceTrackers(trackers);
|
||||
m_model->torrent()->replaceTrackers(adjustedTrackers);
|
||||
}
|
||||
|
||||
void TrackerListWidget::openAddTrackersDialog()
|
||||
@@ -205,7 +221,7 @@ void TrackerListWidget::copyTrackerUrl()
|
||||
if (!torrent())
|
||||
return;
|
||||
|
||||
const auto &selectedTrackerIndexes = getSelectedTrackerRows();
|
||||
const QModelIndexList selectedTrackerIndexes = getSelectedTrackerRows();
|
||||
if (selectedTrackerIndexes.isEmpty())
|
||||
return;
|
||||
|
||||
@@ -226,7 +242,7 @@ void TrackerListWidget::deleteSelectedTrackers()
|
||||
if (!torrent())
|
||||
return;
|
||||
|
||||
const auto &selectedTrackerIndexes = getSelectedTrackerRows();
|
||||
const QModelIndexList selectedTrackerIndexes = getSelectedTrackerRows();
|
||||
if (selectedTrackerIndexes.isEmpty())
|
||||
return;
|
||||
|
||||
@@ -245,7 +261,7 @@ void TrackerListWidget::editSelectedTracker()
|
||||
if (!torrent())
|
||||
return;
|
||||
|
||||
const auto &selectedTrackerIndexes = getSelectedTrackerRows();
|
||||
const QModelIndexList selectedTrackerIndexes = getSelectedTrackerRows();
|
||||
if (selectedTrackerIndexes.isEmpty())
|
||||
return;
|
||||
|
||||
@@ -268,24 +284,36 @@ void TrackerListWidget::editSelectedTracker()
|
||||
if (newTrackerURL == trackerURL)
|
||||
return;
|
||||
|
||||
QList<BitTorrent::TrackerEntry> trackers = torrent()->trackers();
|
||||
const QList<BitTorrent::TrackerEntryStatus> trackers = torrent()->trackers();
|
||||
QList<BitTorrent::TrackerEntry> entries;
|
||||
entries.reserve(trackers.size());
|
||||
|
||||
bool match = false;
|
||||
for (BitTorrent::TrackerEntry &entry : trackers)
|
||||
for (const BitTorrent::TrackerEntryStatus &status : trackers)
|
||||
{
|
||||
if (newTrackerURL == QUrl(entry.url))
|
||||
const QUrl url {status.url};
|
||||
|
||||
if (newTrackerURL == url)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Tracker editing failed"), tr("The tracker URL already exists."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!match && (trackerURL == QUrl(entry.url)))
|
||||
BitTorrent::TrackerEntry entry
|
||||
{
|
||||
.url = status.url,
|
||||
.tier = status.tier
|
||||
};
|
||||
|
||||
if (!match && (trackerURL == url))
|
||||
{
|
||||
match = true;
|
||||
entry.url = newTrackerURL.toString();
|
||||
}
|
||||
entries.append(entry);
|
||||
}
|
||||
|
||||
torrent()->replaceTrackers(trackers);
|
||||
torrent()->replaceTrackers(entries);
|
||||
}
|
||||
|
||||
void TrackerListWidget::reannounceSelected()
|
||||
@@ -315,14 +343,12 @@ void TrackerListWidget::reannounceSelected()
|
||||
trackerURLs.insert(index.siblingAtColumn(TrackerListModel::COL_URL).data().toString());
|
||||
}
|
||||
|
||||
const QList<BitTorrent::TrackerEntry> &trackers = m_model->torrent()->trackers();
|
||||
const QList<BitTorrent::TrackerEntryStatus> &trackers = m_model->torrent()->trackers();
|
||||
for (qsizetype i = 0; i < trackers.size(); ++i)
|
||||
{
|
||||
const BitTorrent::TrackerEntry &trackerEntry = trackers.at(i);
|
||||
if (trackerURLs.contains(trackerEntry.url))
|
||||
{
|
||||
const BitTorrent::TrackerEntryStatus &status = trackers.at(i);
|
||||
if (trackerURLs.contains(status.url))
|
||||
torrent()->forceReannounce(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
|
||||
#include "base/algorithm.h"
|
||||
#include "base/bittorrent/session.h"
|
||||
#include "base/bittorrent/trackerentry.h"
|
||||
#include "base/bittorrent/trackerentrystatus.h"
|
||||
#include "base/global.h"
|
||||
#include "base/net/downloadmanager.h"
|
||||
#include "base/preferences.h"
|
||||
@@ -202,16 +204,15 @@ void TrackersFilterWidget::refreshTrackers(const BitTorrent::Torrent *torrent)
|
||||
return false;
|
||||
});
|
||||
|
||||
const QVector<BitTorrent::TrackerEntry> trackerEntries = torrent->trackers();
|
||||
const bool isTrackerless = trackerEntries.isEmpty();
|
||||
if (isTrackerless)
|
||||
const QVector<BitTorrent::TrackerEntryStatus> trackers = torrent->trackers();
|
||||
if (trackers.isEmpty())
|
||||
{
|
||||
addItems(NULL_HOST, {torrentID});
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const BitTorrent::TrackerEntry &trackerEntry : trackerEntries)
|
||||
addItems(trackerEntry.url, {torrentID});
|
||||
for (const BitTorrent::TrackerEntryStatus &status : trackers)
|
||||
addItems(status.url, {torrentID});
|
||||
}
|
||||
|
||||
item(OTHERERROR_ROW)->setText(formatItemText(OTHERERROR_ROW, m_errors.size()));
|
||||
@@ -380,8 +381,8 @@ void TrackersFilterWidget::setDownloadTrackerFavicon(bool value)
|
||||
}
|
||||
}
|
||||
|
||||
void TrackersFilterWidget::handleTrackerEntriesUpdated(const BitTorrent::Torrent *torrent
|
||||
, const QHash<QString, BitTorrent::TrackerEntry> &updatedTrackerEntries)
|
||||
void TrackersFilterWidget::handleTrackerStatusesUpdated(const BitTorrent::Torrent *torrent
|
||||
, const QHash<QString, BitTorrent::TrackerEntryStatus> &updatedTrackers)
|
||||
{
|
||||
const BitTorrent::TorrentID id = torrent->id();
|
||||
|
||||
@@ -389,51 +390,51 @@ void TrackersFilterWidget::handleTrackerEntriesUpdated(const BitTorrent::Torrent
|
||||
auto trackerErrorHashesIt = m_trackerErrors.find(id);
|
||||
auto warningHashesIt = m_warnings.find(id);
|
||||
|
||||
for (const BitTorrent::TrackerEntry &trackerEntry : updatedTrackerEntries)
|
||||
for (const BitTorrent::TrackerEntryStatus &trackerEntryStatus : updatedTrackers)
|
||||
{
|
||||
if (trackerEntry.status == BitTorrent::TrackerEntryStatus::Working)
|
||||
if (trackerEntryStatus.state == BitTorrent::TrackerEndpointState::Working)
|
||||
{
|
||||
if (errorHashesIt != m_errors.end())
|
||||
{
|
||||
errorHashesIt->remove(trackerEntry.url);
|
||||
errorHashesIt->remove(trackerEntryStatus.url);
|
||||
}
|
||||
|
||||
if (trackerErrorHashesIt != m_trackerErrors.end())
|
||||
{
|
||||
trackerErrorHashesIt->remove(trackerEntry.url);
|
||||
trackerErrorHashesIt->remove(trackerEntryStatus.url);
|
||||
}
|
||||
|
||||
const bool hasNoWarningMessages = std::all_of(trackerEntry.endpointEntries.cbegin(), trackerEntry.endpointEntries.cend()
|
||||
, [](const BitTorrent::TrackerEndpointEntry &endpointEntry)
|
||||
const bool hasNoWarningMessages = std::all_of(trackerEntryStatus.endpoints.cbegin(), trackerEntryStatus.endpoints.cend()
|
||||
, [](const BitTorrent::TrackerEndpointStatus &endpointEntry)
|
||||
{
|
||||
return endpointEntry.message.isEmpty() || (endpointEntry.status != BitTorrent::TrackerEntryStatus::Working);
|
||||
return endpointEntry.message.isEmpty() || (endpointEntry.state != BitTorrent::TrackerEndpointState::Working);
|
||||
});
|
||||
if (hasNoWarningMessages)
|
||||
{
|
||||
if (warningHashesIt != m_warnings.end())
|
||||
{
|
||||
warningHashesIt->remove(trackerEntry.url);
|
||||
warningHashesIt->remove(trackerEntryStatus.url);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (warningHashesIt == m_warnings.end())
|
||||
warningHashesIt = m_warnings.insert(id, {});
|
||||
warningHashesIt->insert(trackerEntry.url);
|
||||
warningHashesIt->insert(trackerEntryStatus.url);
|
||||
}
|
||||
}
|
||||
else if ((trackerEntry.status == BitTorrent::TrackerEntryStatus::NotWorking)
|
||||
|| (trackerEntry.status == BitTorrent::TrackerEntryStatus::Unreachable))
|
||||
else if ((trackerEntryStatus.state == BitTorrent::TrackerEndpointState::NotWorking)
|
||||
|| (trackerEntryStatus.state == BitTorrent::TrackerEndpointState::Unreachable))
|
||||
{
|
||||
if (errorHashesIt == m_errors.end())
|
||||
errorHashesIt = m_errors.insert(id, {});
|
||||
errorHashesIt->insert(trackerEntry.url);
|
||||
errorHashesIt->insert(trackerEntryStatus.url);
|
||||
}
|
||||
else if (trackerEntry.status == BitTorrent::TrackerEntryStatus::TrackerError)
|
||||
else if (trackerEntryStatus.state == BitTorrent::TrackerEndpointState::TrackerError)
|
||||
{
|
||||
if (trackerErrorHashesIt == m_trackerErrors.end())
|
||||
trackerErrorHashesIt = m_trackerErrors.insert(id, {});
|
||||
trackerErrorHashesIt->insert(trackerEntry.url);
|
||||
trackerErrorHashesIt->insert(trackerEntryStatus.url);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,10 +482,10 @@ void TrackersFilterWidget::removeTracker(const QString &tracker)
|
||||
continue;
|
||||
|
||||
QStringList trackersToRemove;
|
||||
for (const BitTorrent::TrackerEntry &trackerEntry : asConst(torrent->trackers()))
|
||||
for (const BitTorrent::TrackerEntryStatus &trackerEntryStatus : asConst(torrent->trackers()))
|
||||
{
|
||||
if ((trackerEntry.url == tracker) || (QUrl(trackerEntry.url).host() == tracker))
|
||||
trackersToRemove.append(trackerEntry.url);
|
||||
if ((trackerEntryStatus.url == tracker) || (QUrl(trackerEntryStatus.url).host() == tracker))
|
||||
trackersToRemove.append(trackerEntryStatus.url);
|
||||
}
|
||||
|
||||
torrent->removeTrackers({trackersToRemove});
|
||||
@@ -592,8 +593,8 @@ void TrackersFilterWidget::handleTorrentsLoaded(const QVector<BitTorrent::Torren
|
||||
for (const BitTorrent::Torrent *torrent : torrents)
|
||||
{
|
||||
const BitTorrent::TorrentID torrentID = torrent->id();
|
||||
const QVector<BitTorrent::TrackerEntry> trackers = torrent->trackers();
|
||||
for (const BitTorrent::TrackerEntry &tracker : trackers)
|
||||
const QVector<BitTorrent::TrackerEntryStatus> trackers = torrent->trackers();
|
||||
for (const BitTorrent::TrackerEntryStatus &tracker : trackers)
|
||||
torrentsPerTracker[tracker.url].append(torrentID);
|
||||
|
||||
// Check for trackerless torrent
|
||||
@@ -613,8 +614,8 @@ void TrackersFilterWidget::handleTorrentsLoaded(const QVector<BitTorrent::Torren
|
||||
void TrackersFilterWidget::torrentAboutToBeDeleted(BitTorrent::Torrent *const torrent)
|
||||
{
|
||||
const BitTorrent::TorrentID torrentID = torrent->id();
|
||||
const QVector<BitTorrent::TrackerEntry> trackers = torrent->trackers();
|
||||
for (const BitTorrent::TrackerEntry &tracker : trackers)
|
||||
const QVector<BitTorrent::TrackerEntryStatus> trackers = torrent->trackers();
|
||||
for (const BitTorrent::TrackerEntryStatus &tracker : trackers)
|
||||
removeItem(tracker.url, torrentID);
|
||||
|
||||
// Check for trackerless torrent
|
||||
|
||||
@@ -32,12 +32,17 @@
|
||||
#include <QtContainerFwd>
|
||||
#include <QHash>
|
||||
|
||||
#include "base/bittorrent/trackerentry.h"
|
||||
#include "base/path.h"
|
||||
#include "basefilterwidget.h"
|
||||
|
||||
class TransferListWidget;
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
struct TrackerEntry;
|
||||
struct TrackerEntryStatus;
|
||||
}
|
||||
|
||||
namespace Net
|
||||
{
|
||||
struct DownloadResult;
|
||||
@@ -55,8 +60,8 @@ public:
|
||||
void addTrackers(const BitTorrent::Torrent *torrent, const QVector<BitTorrent::TrackerEntry> &trackers);
|
||||
void removeTrackers(const BitTorrent::Torrent *torrent, const QStringList &trackers);
|
||||
void refreshTrackers(const BitTorrent::Torrent *torrent);
|
||||
void handleTrackerEntriesUpdated(const BitTorrent::Torrent *torrent
|
||||
, const QHash<QString, BitTorrent::TrackerEntry> &updatedTrackerEntries);
|
||||
void handleTrackerStatusesUpdated(const BitTorrent::Torrent *torrent
|
||||
, const QHash<QString, BitTorrent::TrackerEntryStatus> &updatedTrackers);
|
||||
void setDownloadTrackerFavicon(bool value);
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "base/algorithm.h"
|
||||
#include "base/bittorrent/session.h"
|
||||
#include "base/bittorrent/torrent.h"
|
||||
#include "base/bittorrent/trackerentrystatus.h"
|
||||
#include "base/global.h"
|
||||
#include "base/logger.h"
|
||||
#include "base/net/downloadmanager.h"
|
||||
@@ -191,10 +192,10 @@ void TransferListFiltersWidget::refreshTrackers(const BitTorrent::Torrent *torre
|
||||
m_trackersFilterWidget->refreshTrackers(torrent);
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::trackerEntriesUpdated(const BitTorrent::Torrent *torrent
|
||||
, const QHash<QString, BitTorrent::TrackerEntry> &updatedTrackerEntries)
|
||||
void TransferListFiltersWidget::trackerEntryStatusesUpdated(const BitTorrent::Torrent *torrent
|
||||
, const QHash<QString, BitTorrent::TrackerEntryStatus> &updatedTrackers)
|
||||
{
|
||||
m_trackersFilterWidget->handleTrackerEntriesUpdated(torrent, updatedTrackerEntries);
|
||||
m_trackersFilterWidget->handleTrackerStatusesUpdated(torrent, updatedTrackers);
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::onCategoryFilterStateChanged(bool enabled)
|
||||
|
||||
@@ -30,10 +30,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtContainerFwd>
|
||||
#include <QHash>
|
||||
#include <QWidget>
|
||||
|
||||
#include "base/bittorrent/torrent.h"
|
||||
#include "base/bittorrent/trackerentry.h"
|
||||
|
||||
class CategoryFilterWidget;
|
||||
@@ -42,6 +40,12 @@ class TagFilterWidget;
|
||||
class TrackersFilterWidget;
|
||||
class TransferListWidget;
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class Torrent;
|
||||
struct TrackerEntryStatus;
|
||||
}
|
||||
|
||||
class TransferListFiltersWidget final : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -55,8 +59,8 @@ public slots:
|
||||
void addTrackers(const BitTorrent::Torrent *torrent, const QVector<BitTorrent::TrackerEntry> &trackers);
|
||||
void removeTrackers(const BitTorrent::Torrent *torrent, const QStringList &trackers);
|
||||
void refreshTrackers(const BitTorrent::Torrent *torrent);
|
||||
void trackerEntriesUpdated(const BitTorrent::Torrent *torrent
|
||||
, const QHash<QString, BitTorrent::TrackerEntry> &updatedTrackerEntries);
|
||||
void trackerEntryStatusesUpdated(const BitTorrent::Torrent *torrent
|
||||
, const QHash<QString, BitTorrent::TrackerEntryStatus> &updatedTrackers);
|
||||
|
||||
private slots:
|
||||
void onCategoryFilterStateChanged(bool enabled);
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
#include "base/bittorrent/session.h"
|
||||
#include "base/bittorrent/torrent.h"
|
||||
#include "base/bittorrent/trackerentry.h"
|
||||
#include "base/bittorrent/trackerentrystatus.h"
|
||||
#include "base/global.h"
|
||||
#include "base/logger.h"
|
||||
#include "base/path.h"
|
||||
@@ -783,14 +783,14 @@ void TransferListWidget::editTorrentTrackers()
|
||||
|
||||
if (!torrents.empty())
|
||||
{
|
||||
commonTrackers = torrents[0]->trackers();
|
||||
for (const BitTorrent::TrackerEntryStatus &status : asConst(torrents[0]->trackers()))
|
||||
commonTrackers.append({.url = status.url, .tier = status.tier});
|
||||
|
||||
for (const BitTorrent::Torrent *torrent : torrents)
|
||||
{
|
||||
QSet<BitTorrent::TrackerEntry> trackerSet;
|
||||
|
||||
for (const BitTorrent::TrackerEntry &entry : asConst(torrent->trackers()))
|
||||
trackerSet.insert(entry);
|
||||
for (const BitTorrent::TrackerEntryStatus &status : asConst(torrent->trackers()))
|
||||
trackerSet.insert({.url = status.url, .tier = status.tier});
|
||||
|
||||
commonTrackers.erase(std::remove_if(commonTrackers.begin(), commonTrackers.end()
|
||||
, [&trackerSet](const BitTorrent::TrackerEntry &entry) { return !trackerSet.contains(entry); })
|
||||
|
||||
Reference in New Issue
Block a user