mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-15 01:33:07 -07:00
parent
dd1bd8ad10
commit
4a7f1116ac
7 changed files with 222 additions and 168 deletions
|
@ -291,6 +291,67 @@ namespace
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
|
TrackerEntryUpdateInfo getTrackerEntryUpdateInfo(const lt::announce_entry &nativeEntry, const lt::info_hash_t &hashes)
|
||||||
|
#else
|
||||||
|
TrackerEntryUpdateInfo getTrackerEntryUpdateInfo(const lt::announce_entry &nativeEntry)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
TrackerEntryUpdateInfo result {};
|
||||||
|
int numUpdating = 0;
|
||||||
|
int numWorking = 0;
|
||||||
|
int numNotWorking = 0;
|
||||||
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
|
const auto numEndpoints = static_cast<qsizetype>(nativeEntry.endpoints.size() * ((hashes.has_v1() && hashes.has_v2()) ? 2 : 1));
|
||||||
|
for (const lt::announce_endpoint &endpoint : nativeEntry.endpoints)
|
||||||
|
{
|
||||||
|
for (const auto protocolVersion : {lt::protocol_version::V1, lt::protocol_version::V2})
|
||||||
|
{
|
||||||
|
if (hashes.has(protocolVersion))
|
||||||
|
{
|
||||||
|
const lt::announce_infohash &infoHash = endpoint.info_hashes[protocolVersion];
|
||||||
|
|
||||||
|
if (!result.hasMessages)
|
||||||
|
result.hasMessages = !infoHash.message.empty();
|
||||||
|
|
||||||
|
if (infoHash.updating)
|
||||||
|
++numUpdating;
|
||||||
|
else if (infoHash.fails > 0)
|
||||||
|
++numNotWorking;
|
||||||
|
else if (nativeEntry.verified)
|
||||||
|
++numWorking;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
const auto numEndpoints = static_cast<qsizetype>(nativeEntry.endpoints.size());
|
||||||
|
for (const lt::announce_endpoint &endpoint : nativeEntry.endpoints)
|
||||||
|
{
|
||||||
|
if (!result.hasMessages)
|
||||||
|
result.hasMessages = !endpoint.message.empty();
|
||||||
|
|
||||||
|
if (endpoint.updating)
|
||||||
|
++numUpdating;
|
||||||
|
else if (endpoint.fails > 0)
|
||||||
|
++numNotWorking;
|
||||||
|
else if (nativeEntry.verified)
|
||||||
|
++numWorking;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (numEndpoints > 0)
|
||||||
|
{
|
||||||
|
if (numUpdating > 0)
|
||||||
|
result.status = TrackerEntry::Updating;
|
||||||
|
else if (numWorking > 0)
|
||||||
|
result.status = TrackerEntry::Working;
|
||||||
|
else if (numNotWorking == numEndpoints)
|
||||||
|
result.status = TrackerEntry::NotWorking;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int addTorrentParamsId = qRegisterMetaType<AddTorrentParams>();
|
const int addTorrentParamsId = qRegisterMetaType<AddTorrentParams>();
|
||||||
|
@ -4033,16 +4094,6 @@ void Session::handleTorrentResumeDataReady(TorrentImpl *const torrent, const Loa
|
||||||
m_resumeDataStorage->store(torrent->id(), data);
|
m_resumeDataStorage->store(torrent->id(), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::handleTorrentTrackerReply(TorrentImpl *const torrent, const QString &trackerUrl)
|
|
||||||
{
|
|
||||||
emit trackerSuccess(torrent, trackerUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Session::handleTorrentTrackerError(TorrentImpl *const torrent, const QString &trackerUrl)
|
|
||||||
{
|
|
||||||
emit trackerError(torrent, trackerUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Session::addMoveTorrentStorageJob(TorrentImpl *torrent, const Path &newPath, const MoveStorageMode mode)
|
bool Session::addMoveTorrentStorageJob(TorrentImpl *torrent, const Path &newPath, const MoveStorageMode mode)
|
||||||
{
|
{
|
||||||
Q_ASSERT(torrent);
|
Q_ASSERT(torrent);
|
||||||
|
@ -4233,11 +4284,6 @@ void Session::loadCategories()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::handleTorrentTrackerWarning(TorrentImpl *const torrent, const QString &trackerUrl)
|
|
||||||
{
|
|
||||||
emit trackerWarning(torrent, trackerUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Session::hasPerTorrentRatioLimit() const
|
bool Session::hasPerTorrentRatioLimit() const
|
||||||
{
|
{
|
||||||
return std::any_of(m_torrents.cbegin(), m_torrents.cend(), [](const TorrentImpl *torrent)
|
return std::any_of(m_torrents.cbegin(), m_torrents.cend(), [](const TorrentImpl *torrent)
|
||||||
|
@ -4562,6 +4608,8 @@ void Session::readAlerts()
|
||||||
const std::vector<lt::alert *> alerts = getPendingAlerts();
|
const std::vector<lt::alert *> alerts = getPendingAlerts();
|
||||||
for (const lt::alert *a : alerts)
|
for (const lt::alert *a : alerts)
|
||||||
handleAlert(a);
|
handleAlert(a);
|
||||||
|
|
||||||
|
processTrackerStatuses();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::handleAlert(const lt::alert *a)
|
void Session::handleAlert(const lt::alert *a)
|
||||||
|
@ -4581,9 +4629,6 @@ void Session::handleAlert(const lt::alert *a)
|
||||||
case lt::save_resume_data_failed_alert::alert_type:
|
case lt::save_resume_data_failed_alert::alert_type:
|
||||||
case lt::torrent_paused_alert::alert_type:
|
case lt::torrent_paused_alert::alert_type:
|
||||||
case lt::torrent_resumed_alert::alert_type:
|
case lt::torrent_resumed_alert::alert_type:
|
||||||
case lt::tracker_error_alert::alert_type:
|
|
||||||
case lt::tracker_reply_alert::alert_type:
|
|
||||||
case lt::tracker_warning_alert::alert_type:
|
|
||||||
case lt::fastresume_rejected_alert::alert_type:
|
case lt::fastresume_rejected_alert::alert_type:
|
||||||
case lt::torrent_checked_alert::alert_type:
|
case lt::torrent_checked_alert::alert_type:
|
||||||
case lt::metadata_received_alert::alert_type:
|
case lt::metadata_received_alert::alert_type:
|
||||||
|
@ -4596,6 +4641,11 @@ void Session::handleAlert(const lt::alert *a)
|
||||||
case lt::session_stats_alert::alert_type:
|
case lt::session_stats_alert::alert_type:
|
||||||
handleSessionStatsAlert(static_cast<const lt::session_stats_alert*>(a));
|
handleSessionStatsAlert(static_cast<const lt::session_stats_alert*>(a));
|
||||||
break;
|
break;
|
||||||
|
case lt::tracker_error_alert::alert_type:
|
||||||
|
case lt::tracker_reply_alert::alert_type:
|
||||||
|
case lt::tracker_warning_alert::alert_type:
|
||||||
|
handleTrackerAlert(static_cast<const lt::tracker_alert *>(a));
|
||||||
|
break;
|
||||||
case lt::file_error_alert::alert_type:
|
case lt::file_error_alert::alert_type:
|
||||||
handleFileErrorAlert(static_cast<const lt::file_error_alert*>(a));
|
handleFileErrorAlert(static_cast<const lt::file_error_alert*>(a));
|
||||||
break;
|
break;
|
||||||
|
@ -5133,3 +5183,50 @@ void Session::handleSocks5Alert(const lt::socks5_alert *p) const
|
||||||
, Log::WARNING);
|
, Log::WARNING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Session::handleTrackerAlert(const lt::tracker_alert *a)
|
||||||
|
{
|
||||||
|
TorrentImpl *torrent = m_torrents.value(a->handle.info_hash());
|
||||||
|
if (!torrent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QByteArray trackerURL {a->tracker_url()};
|
||||||
|
m_updatedTrackerEntries[torrent].insert(trackerURL);
|
||||||
|
|
||||||
|
if (a->type() == lt::tracker_reply_alert::alert_type)
|
||||||
|
{
|
||||||
|
const int numPeers = static_cast<const lt::tracker_reply_alert *>(a)->num_peers;
|
||||||
|
torrent->updatePeerCount(trackerURL, a->local_endpoint, numPeers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::processTrackerStatuses()
|
||||||
|
{
|
||||||
|
QHash<Torrent *, QHash<QString, TrackerEntryUpdateInfo>> updateInfos;
|
||||||
|
|
||||||
|
for (auto it = m_updatedTrackerEntries.cbegin(); it != m_updatedTrackerEntries.cend(); ++it)
|
||||||
|
{
|
||||||
|
TorrentImpl *torrent = it.key();
|
||||||
|
const QSet<QByteArray> &updatedTrackers = it.value();
|
||||||
|
|
||||||
|
const std::vector<lt::announce_entry> trackerList = torrent->nativeHandle().trackers();
|
||||||
|
for (const lt::announce_entry &announceEntry : trackerList)
|
||||||
|
{
|
||||||
|
const auto trackerURL = QByteArray::fromRawData(announceEntry.url.c_str(), announceEntry.url.size());
|
||||||
|
if (!updatedTrackers.contains(trackerURL))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
#ifdef QBT_USES_LIBTORRENT2
|
||||||
|
const TrackerEntryUpdateInfo updateInfo = getTrackerEntryUpdateInfo(announceEntry, torrent->nativeHandle().info_hashes());
|
||||||
|
#else
|
||||||
|
const TrackerEntryUpdateInfo updateInfo = getTrackerEntryUpdateInfo(announceEntry);
|
||||||
|
#endif
|
||||||
|
if ((updateInfo.status == TrackerEntry::Working) || (updateInfo.status == TrackerEntry::NotWorking))
|
||||||
|
updateInfos[torrent][QString::fromUtf8(trackerURL)] = updateInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_updatedTrackerEntries.clear();
|
||||||
|
if (!updateInfos.isEmpty())
|
||||||
|
emit trackerEntriesUpdated(updateInfos);
|
||||||
|
}
|
||||||
|
|
|
@ -203,6 +203,12 @@ namespace BitTorrent
|
||||||
} disk;
|
} disk;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TrackerEntryUpdateInfo
|
||||||
|
{
|
||||||
|
TrackerEntry::Status status = TrackerEntry::NotContacted;
|
||||||
|
bool hasMessages = false;
|
||||||
|
};
|
||||||
|
|
||||||
class Session final : public QObject
|
class Session final : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -498,9 +504,6 @@ namespace BitTorrent
|
||||||
void handleTorrentUrlSeedsAdded(TorrentImpl *const torrent, const QVector<QUrl> &newUrlSeeds);
|
void handleTorrentUrlSeedsAdded(TorrentImpl *const torrent, const QVector<QUrl> &newUrlSeeds);
|
||||||
void handleTorrentUrlSeedsRemoved(TorrentImpl *const torrent, const QVector<QUrl> &urlSeeds);
|
void handleTorrentUrlSeedsRemoved(TorrentImpl *const torrent, const QVector<QUrl> &urlSeeds);
|
||||||
void handleTorrentResumeDataReady(TorrentImpl *const torrent, const LoadTorrentParams &data);
|
void handleTorrentResumeDataReady(TorrentImpl *const torrent, const LoadTorrentParams &data);
|
||||||
void handleTorrentTrackerReply(TorrentImpl *const torrent, const QString &trackerUrl);
|
|
||||||
void handleTorrentTrackerWarning(TorrentImpl *const torrent, const QString &trackerUrl);
|
|
||||||
void handleTorrentTrackerError(TorrentImpl *const torrent, const QString &trackerUrl);
|
|
||||||
|
|
||||||
bool addMoveTorrentStorageJob(TorrentImpl *torrent, const Path &newPath, MoveStorageMode mode);
|
bool addMoveTorrentStorageJob(TorrentImpl *torrent, const Path &newPath, MoveStorageMode mode);
|
||||||
|
|
||||||
|
@ -544,6 +547,7 @@ namespace BitTorrent
|
||||||
void trackersRemoved(Torrent *torrent, const QVector<TrackerEntry> &trackers);
|
void trackersRemoved(Torrent *torrent, const QVector<TrackerEntry> &trackers);
|
||||||
void trackerSuccess(Torrent *torrent, const QString &tracker);
|
void trackerSuccess(Torrent *torrent, const QString &tracker);
|
||||||
void trackerWarning(Torrent *torrent, const QString &tracker);
|
void trackerWarning(Torrent *torrent, const QString &tracker);
|
||||||
|
void trackerEntriesUpdated(const QHash<Torrent *, QHash<QString, TrackerEntryUpdateInfo>> &updateInfos);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void configureDeferred();
|
void configureDeferred();
|
||||||
|
@ -606,6 +610,7 @@ namespace BitTorrent
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
void applyOSMemoryPriority() const;
|
void applyOSMemoryPriority() const;
|
||||||
#endif
|
#endif
|
||||||
|
void processTrackerStatuses();
|
||||||
|
|
||||||
bool loadTorrent(LoadTorrentParams params);
|
bool loadTorrent(LoadTorrentParams params);
|
||||||
LoadTorrentParams initLoadTorrentParams(const AddTorrentParams &addTorrentParams);
|
LoadTorrentParams initLoadTorrentParams(const AddTorrentParams &addTorrentParams);
|
||||||
|
@ -636,6 +641,7 @@ namespace BitTorrent
|
||||||
void handleStorageMovedAlert(const lt::storage_moved_alert *p);
|
void handleStorageMovedAlert(const lt::storage_moved_alert *p);
|
||||||
void handleStorageMovedFailedAlert(const lt::storage_moved_failed_alert *p);
|
void handleStorageMovedFailedAlert(const lt::storage_moved_failed_alert *p);
|
||||||
void handleSocks5Alert(const lt::socks5_alert *p) const;
|
void handleSocks5Alert(const lt::socks5_alert *p) const;
|
||||||
|
void handleTrackerAlert(const lt::tracker_alert *a);
|
||||||
|
|
||||||
void createTorrent(const lt::torrent_handle &nativeHandle);
|
void createTorrent(const lt::torrent_handle &nativeHandle);
|
||||||
|
|
||||||
|
@ -793,6 +799,8 @@ namespace BitTorrent
|
||||||
QMap<QString, CategoryOptions> m_categories;
|
QMap<QString, CategoryOptions> m_categories;
|
||||||
QSet<QString> m_tags;
|
QSet<QString> m_tags;
|
||||||
|
|
||||||
|
QHash<TorrentImpl *, QSet<QByteArray>> m_updatedTrackerEntries;
|
||||||
|
|
||||||
// I/O errored torrents
|
// I/O errored torrents
|
||||||
QSet<TorrentID> m_recentErroredTorrents;
|
QSet<TorrentID> m_recentErroredTorrents;
|
||||||
QTimer *m_recentErroredTorrentsTimer = nullptr;
|
QTimer *m_recentErroredTorrentsTimer = nullptr;
|
||||||
|
|
|
@ -69,7 +69,7 @@ using namespace BitTorrent;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
lt::announce_entry makeNativeAnnouncerEntry(const QString &url, const int tier)
|
lt::announce_entry makeNativeAnnounceEntry(const QString &url, const int tier)
|
||||||
{
|
{
|
||||||
lt::announce_entry entry {url.toStdString()};
|
lt::announce_entry entry {url.toStdString()};
|
||||||
entry.tier = tier;
|
entry.tier = tier;
|
||||||
|
@ -536,7 +536,7 @@ void TorrentImpl::addTrackers(const QVector<TrackerEntry> &trackers)
|
||||||
{
|
{
|
||||||
if (!currentTrackers.contains(tracker))
|
if (!currentTrackers.contains(tracker))
|
||||||
{
|
{
|
||||||
m_nativeHandle.add_tracker(makeNativeAnnouncerEntry(tracker.url, tracker.tier));
|
m_nativeHandle.add_tracker(makeNativeAnnounceEntry(tracker.url, tracker.tier));
|
||||||
newTrackers << tracker;
|
newTrackers << tracker;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -560,7 +560,7 @@ void TorrentImpl::replaceTrackers(const QVector<TrackerEntry> &trackers)
|
||||||
|
|
||||||
for (const TrackerEntry &tracker : trackers)
|
for (const TrackerEntry &tracker : trackers)
|
||||||
{
|
{
|
||||||
nativeTrackers.emplace_back(makeNativeAnnouncerEntry(tracker.url, tracker.tier));
|
nativeTrackers.emplace_back(makeNativeAnnounceEntry(tracker.url, tracker.tier));
|
||||||
|
|
||||||
if (!currentTrackers.removeOne(tracker))
|
if (!currentTrackers.removeOne(tracker))
|
||||||
newTrackers << tracker;
|
newTrackers << tracker;
|
||||||
|
@ -1484,6 +1484,11 @@ void TorrentImpl::fileSearchFinished(const Path &savePath, const PathList &fileN
|
||||||
endReceivedMetadataHandling(savePath, fileNames);
|
endReceivedMetadataHandling(savePath, fileNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TorrentImpl::updatePeerCount(const QString &trackerUrl, const lt::tcp::endpoint &endpoint, const int count)
|
||||||
|
{
|
||||||
|
m_trackerPeerCounts[trackerUrl][endpoint] = count;
|
||||||
|
}
|
||||||
|
|
||||||
void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathList &fileNames)
|
void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathList &fileNames)
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_filePaths.isEmpty());
|
Q_ASSERT(m_filePaths.isEmpty());
|
||||||
|
@ -1665,46 +1670,6 @@ void TorrentImpl::handleMoveStorageJobFinished(const bool hasOutstandingJob)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentImpl::handleTrackerReplyAlert(const lt::tracker_reply_alert *p)
|
|
||||||
{
|
|
||||||
const QString trackerUrl = p->tracker_url();
|
|
||||||
m_trackerPeerCounts[trackerUrl][p->local_endpoint] = p->num_peers;
|
|
||||||
|
|
||||||
m_session->handleTorrentTrackerReply(this, trackerUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TorrentImpl::handleTrackerWarningAlert(const lt::tracker_warning_alert *p)
|
|
||||||
{
|
|
||||||
const QString trackerUrl = p->tracker_url();
|
|
||||||
m_session->handleTorrentTrackerWarning(this, trackerUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TorrentImpl::handleTrackerErrorAlert(const lt::tracker_error_alert *p)
|
|
||||||
{
|
|
||||||
// Starting with libtorrent 1.2.x each tracker has multiple local endpoints from which
|
|
||||||
// an announce is attempted. Some endpoints might succeed while others might fail.
|
|
||||||
// Emit the signal only if all endpoints have failed.
|
|
||||||
const std::vector<lt::announce_entry> trackerList = m_nativeHandle.trackers();
|
|
||||||
const auto iter = std::find_if(trackerList.cbegin(), trackerList.cend(), [p](const lt::announce_entry &entry)
|
|
||||||
{
|
|
||||||
return (entry.url == p->tracker_url());
|
|
||||||
});
|
|
||||||
|
|
||||||
if (iter == trackerList.cend())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const QString trackerURL = QString::fromStdString(iter->url);
|
|
||||||
|
|
||||||
#ifdef QBT_USES_LIBTORRENT2
|
|
||||||
const TrackerEntry entry = fromNativeAnnounceEntry(*iter, m_nativeHandle.info_hashes(), m_trackerPeerCounts[trackerURL]);
|
|
||||||
#else
|
|
||||||
const TrackerEntry entry = fromNativeAnnounceEntry(*iter, m_trackerPeerCounts[trackerURL]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (entry.status == TrackerEntry::NotWorking)
|
|
||||||
m_session->handleTorrentTrackerError(this, trackerURL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TorrentImpl::handleTorrentCheckedAlert(const lt::torrent_checked_alert *p)
|
void TorrentImpl::handleTorrentCheckedAlert(const lt::torrent_checked_alert *p)
|
||||||
{
|
{
|
||||||
Q_UNUSED(p);
|
Q_UNUSED(p);
|
||||||
|
@ -2014,15 +1979,6 @@ void TorrentImpl::handleAlert(const lt::alert *a)
|
||||||
case lt::torrent_resumed_alert::alert_type:
|
case lt::torrent_resumed_alert::alert_type:
|
||||||
handleTorrentResumedAlert(static_cast<const lt::torrent_resumed_alert*>(a));
|
handleTorrentResumedAlert(static_cast<const lt::torrent_resumed_alert*>(a));
|
||||||
break;
|
break;
|
||||||
case lt::tracker_error_alert::alert_type:
|
|
||||||
handleTrackerErrorAlert(static_cast<const lt::tracker_error_alert*>(a));
|
|
||||||
break;
|
|
||||||
case lt::tracker_reply_alert::alert_type:
|
|
||||||
handleTrackerReplyAlert(static_cast<const lt::tracker_reply_alert*>(a));
|
|
||||||
break;
|
|
||||||
case lt::tracker_warning_alert::alert_type:
|
|
||||||
handleTrackerWarningAlert(static_cast<const lt::tracker_warning_alert*>(a));
|
|
||||||
break;
|
|
||||||
case lt::metadata_received_alert::alert_type:
|
case lt::metadata_received_alert::alert_type:
|
||||||
handleMetadataReceivedAlert(static_cast<const lt::metadata_received_alert*>(a));
|
handleMetadataReceivedAlert(static_cast<const lt::metadata_received_alert*>(a));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -239,6 +239,7 @@ namespace BitTorrent
|
||||||
void saveResumeData();
|
void saveResumeData();
|
||||||
void handleMoveStorageJobFinished(bool hasOutstandingJob);
|
void handleMoveStorageJobFinished(bool hasOutstandingJob);
|
||||||
void fileSearchFinished(const Path &savePath, const PathList &fileNames);
|
void fileSearchFinished(const Path &savePath, const PathList &fileNames);
|
||||||
|
void updatePeerCount(const QString &trackerUrl, const lt::tcp::endpoint &endpoint, int count);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using EventTrigger = std::function<void ()>;
|
using EventTrigger = std::function<void ()>;
|
||||||
|
@ -263,9 +264,6 @@ namespace BitTorrent
|
||||||
void handleTorrentFinishedAlert(const lt::torrent_finished_alert *p);
|
void handleTorrentFinishedAlert(const lt::torrent_finished_alert *p);
|
||||||
void handleTorrentPausedAlert(const lt::torrent_paused_alert *p);
|
void handleTorrentPausedAlert(const lt::torrent_paused_alert *p);
|
||||||
void handleTorrentResumedAlert(const lt::torrent_resumed_alert *p);
|
void handleTorrentResumedAlert(const lt::torrent_resumed_alert *p);
|
||||||
void handleTrackerErrorAlert(const lt::tracker_error_alert *p);
|
|
||||||
void handleTrackerReplyAlert(const lt::tracker_reply_alert *p);
|
|
||||||
void handleTrackerWarningAlert(const lt::tracker_warning_alert *p);
|
|
||||||
|
|
||||||
bool isMoveInProgress() const;
|
bool isMoveInProgress() const;
|
||||||
|
|
||||||
|
|
|
@ -243,13 +243,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackersAdded, m_transferListFiltersWidget, &TransferListFiltersWidget::addTrackers);
|
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::trackersRemoved, m_transferListFiltersWidget, &TransferListFiltersWidget::removeTrackers);
|
||||||
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::trackerEntriesUpdated, m_transferListFiltersWidget, &TransferListFiltersWidget::trackerEntriesUpdated);
|
||||||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerSuccess
|
|
||||||
, m_transferListFiltersWidget, qOverload<const BitTorrent::Torrent *, const QString &>(&TransferListFiltersWidget::trackerSuccess));
|
|
||||||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerError
|
|
||||||
, m_transferListFiltersWidget, qOverload<const BitTorrent::Torrent *, const QString &>(&TransferListFiltersWidget::trackerError));
|
|
||||||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerWarning
|
|
||||||
, m_transferListFiltersWidget, qOverload<const BitTorrent::Torrent *, 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
|
||||||
|
|
|
@ -385,13 +385,13 @@ void TrackerFiltersList::addItem(const QString &tracker, const BitTorrent::Torre
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackerFiltersList::removeItem(const QString &tracker, const BitTorrent::TorrentID &id)
|
void TrackerFiltersList::removeItem(const QString &trackerURL, const BitTorrent::TorrentID &id)
|
||||||
{
|
{
|
||||||
const QString host = getHost(tracker);
|
const QString host = getHost(trackerURL);
|
||||||
QSet<BitTorrent::TorrentID> torrentIDs = m_trackers.value(host);
|
QSet<BitTorrent::TorrentID> torrentIDs = m_trackers.value(host);
|
||||||
|
|
||||||
if (torrentIDs.empty())
|
if (torrentIDs.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
torrentIDs.remove(id);
|
torrentIDs.remove(id);
|
||||||
|
|
||||||
int row = 0;
|
int row = 0;
|
||||||
|
@ -400,7 +400,34 @@ void TrackerFiltersList::removeItem(const QString &tracker, const BitTorrent::To
|
||||||
if (!host.isEmpty())
|
if (!host.isEmpty())
|
||||||
{
|
{
|
||||||
// Remove from 'Error' and 'Warning' view
|
// Remove from 'Error' and 'Warning' view
|
||||||
trackerSuccess(id, tracker);
|
const auto errorHashesIt = m_errors.find(id);
|
||||||
|
if (errorHashesIt != m_errors.end())
|
||||||
|
{
|
||||||
|
QSet<QString> &errored = errorHashesIt.value();
|
||||||
|
errored.remove(trackerURL);
|
||||||
|
if (errored.isEmpty())
|
||||||
|
{
|
||||||
|
m_errors.erase(errorHashesIt);
|
||||||
|
item(ERROR_ROW)->setText(tr("Error (%1)").arg(m_errors.size()));
|
||||||
|
if (currentRow() == ERROR_ROW)
|
||||||
|
applyFilter(ERROR_ROW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto warningHashesIt = m_warnings.find(id);
|
||||||
|
if (warningHashesIt != m_warnings.end())
|
||||||
|
{
|
||||||
|
QSet<QString> &warned = *warningHashesIt;
|
||||||
|
warned.remove(trackerURL);
|
||||||
|
if (warned.isEmpty())
|
||||||
|
{
|
||||||
|
m_warnings.erase(warningHashesIt);
|
||||||
|
item(WARNING_ROW)->setText(tr("Warning (%1)").arg(m_warnings.size()));
|
||||||
|
if (currentRow() == WARNING_ROW)
|
||||||
|
applyFilter(WARNING_ROW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
row = rowFromTracker(host);
|
row = rowFromTracker(host);
|
||||||
trackerItem = item(row);
|
trackerItem = item(row);
|
||||||
|
|
||||||
|
@ -458,58 +485,64 @@ void TrackerFiltersList::setDownloadTrackerFavicon(bool value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackerFiltersList::trackerSuccess(const BitTorrent::TorrentID &id, const QString &tracker)
|
void TrackerFiltersList::handleTrackerEntriesUpdated(const QHash<BitTorrent::Torrent *, QHash<QString, BitTorrent::TrackerEntryUpdateInfo>> &updateInfos)
|
||||||
{
|
{
|
||||||
const auto errorHashesIter = m_errors.find(id);
|
for (auto torrentsIt = updateInfos.cbegin(); torrentsIt != updateInfos.cend(); ++torrentsIt)
|
||||||
if (errorHashesIter != m_errors.end())
|
|
||||||
{
|
{
|
||||||
QSet<QString> &errored = *errorHashesIter;
|
const BitTorrent::TorrentID id = torrentsIt.key()->id();
|
||||||
errored.remove(tracker);
|
const QHash<QString, BitTorrent::TrackerEntryUpdateInfo> &infos = torrentsIt.value();
|
||||||
if (errored.empty())
|
|
||||||
|
auto errorHashesIt = m_errors.find(id);
|
||||||
|
auto warningHashesIt = m_warnings.find(id);
|
||||||
|
|
||||||
|
for (auto trackerIt = infos.cbegin(); trackerIt != infos.cend(); ++trackerIt)
|
||||||
{
|
{
|
||||||
m_errors.erase(errorHashesIter);
|
const QString &trackerURL = trackerIt.key();
|
||||||
|
const BitTorrent::TrackerEntryUpdateInfo &updateInfo = trackerIt.value();
|
||||||
|
|
||||||
|
if (updateInfo.status == BitTorrent::TrackerEntry::Working)
|
||||||
|
{
|
||||||
|
if (errorHashesIt != m_errors.end())
|
||||||
|
{
|
||||||
|
QSet<QString> &errored = errorHashesIt.value();
|
||||||
|
errored.remove(trackerURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!updateInfo.hasMessages)
|
||||||
|
{
|
||||||
|
if (warningHashesIt != m_warnings.end())
|
||||||
|
{
|
||||||
|
QSet<QString> &warned = *warningHashesIt;
|
||||||
|
warned.remove(trackerURL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (warningHashesIt == m_warnings.end())
|
||||||
|
warningHashesIt = m_warnings.insert(id, {});
|
||||||
|
warningHashesIt.value().insert(trackerURL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (updateInfo.status == BitTorrent::TrackerEntry::NotWorking)
|
||||||
|
{
|
||||||
|
if (errorHashesIt == m_errors.end())
|
||||||
|
errorHashesIt = m_errors.insert(id, {});
|
||||||
|
errorHashesIt.value().insert(trackerURL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((errorHashesIt != m_errors.end()) && errorHashesIt.value().isEmpty())
|
||||||
|
m_errors.erase(errorHashesIt);
|
||||||
|
if ((warningHashesIt != m_warnings.end()) && warningHashesIt.value().isEmpty())
|
||||||
|
m_warnings.erase(warningHashesIt);
|
||||||
|
}
|
||||||
|
|
||||||
item(ERROR_ROW)->setText(tr("Error (%1)").arg(m_errors.size()));
|
item(ERROR_ROW)->setText(tr("Error (%1)").arg(m_errors.size()));
|
||||||
|
item(WARNING_ROW)->setText(tr("Warning (%1)").arg(m_warnings.size()));
|
||||||
|
|
||||||
if (currentRow() == ERROR_ROW)
|
if (currentRow() == ERROR_ROW)
|
||||||
applyFilter(ERROR_ROW);
|
applyFilter(ERROR_ROW);
|
||||||
}
|
else if (currentRow() == WARNING_ROW)
|
||||||
}
|
|
||||||
|
|
||||||
const auto warningHashesIter = m_warnings.find(id);
|
|
||||||
if (warningHashesIter != m_warnings.end())
|
|
||||||
{
|
|
||||||
QSet<QString> &warned = *warningHashesIter;
|
|
||||||
warned.remove(tracker);
|
|
||||||
if (warned.empty())
|
|
||||||
{
|
|
||||||
m_warnings.erase(warningHashesIter);
|
|
||||||
item(WARNING_ROW)->setText(tr("Warning (%1)").arg(m_warnings.size()));
|
|
||||||
if (currentRow() == WARNING_ROW)
|
|
||||||
applyFilter(WARNING_ROW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TrackerFiltersList::trackerError(const BitTorrent::TorrentID &id, const QString &tracker)
|
|
||||||
{
|
|
||||||
QSet<QString> &trackers {m_errors[id]};
|
|
||||||
if (trackers.contains(tracker))
|
|
||||||
return;
|
|
||||||
|
|
||||||
trackers.insert(tracker);
|
|
||||||
item(ERROR_ROW)->setText(tr("Error (%1)").arg(m_errors.size()));
|
|
||||||
if (currentRow() == ERROR_ROW)
|
|
||||||
applyFilter(ERROR_ROW);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TrackerFiltersList::trackerWarning(const BitTorrent::TorrentID &id, const QString &tracker)
|
|
||||||
{
|
|
||||||
QSet<QString> &trackers {m_warnings[id]};
|
|
||||||
if (trackers.contains(tracker))
|
|
||||||
return;
|
|
||||||
|
|
||||||
trackers.insert(tracker);
|
|
||||||
item(WARNING_ROW)->setText(tr("Warning (%1)").arg(m_warnings.size()));
|
|
||||||
if (currentRow() == WARNING_ROW)
|
|
||||||
applyFilter(WARNING_ROW);
|
applyFilter(WARNING_ROW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -732,13 +765,6 @@ TransferListFiltersWidget::TransferListFiltersWidget(QWidget *parent, TransferLi
|
||||||
connect(statusLabel, &QCheckBox::toggled, pref, &Preferences::setStatusFilterState);
|
connect(statusLabel, &QCheckBox::toggled, pref, &Preferences::setStatusFilterState);
|
||||||
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 BitTorrent::TorrentID &, const QString &>(&TransferListFiltersWidget::trackerSuccess)
|
|
||||||
, m_trackerFilters, &TrackerFiltersList::trackerSuccess);
|
|
||||||
connect(this, qOverload<const BitTorrent::TorrentID &, const QString &>(&TransferListFiltersWidget::trackerError)
|
|
||||||
, m_trackerFilters, &TrackerFiltersList::trackerError);
|
|
||||||
connect(this, qOverload<const BitTorrent::TorrentID &, const QString &>(&TransferListFiltersWidget::trackerWarning)
|
|
||||||
, m_trackerFilters, &TrackerFiltersList::trackerWarning);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListFiltersWidget::setDownloadTrackerFavicon(bool value)
|
void TransferListFiltersWidget::setDownloadTrackerFavicon(bool value)
|
||||||
|
@ -763,19 +789,9 @@ void TransferListFiltersWidget::changeTrackerless(const BitTorrent::Torrent *tor
|
||||||
m_trackerFilters->changeTrackerless(trackerless, torrent->id());
|
m_trackerFilters->changeTrackerless(trackerless, torrent->id());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListFiltersWidget::trackerSuccess(const BitTorrent::Torrent *torrent, const QString &tracker)
|
void TransferListFiltersWidget::trackerEntriesUpdated(const QHash<BitTorrent::Torrent *, QHash<QString, BitTorrent::TrackerEntryUpdateInfo>> &updateInfos)
|
||||||
{
|
{
|
||||||
emit trackerSuccess(torrent->id(), tracker);
|
m_trackerFilters->handleTrackerEntriesUpdated(updateInfos);
|
||||||
}
|
|
||||||
|
|
||||||
void TransferListFiltersWidget::trackerWarning(const BitTorrent::Torrent *torrent, const QString &tracker)
|
|
||||||
{
|
|
||||||
emit trackerWarning(torrent->id(), tracker);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransferListFiltersWidget::trackerError(const BitTorrent::Torrent *torrent, const QString &tracker)
|
|
||||||
{
|
|
||||||
emit trackerError(torrent->id(), tracker);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransferListFiltersWidget::onCategoryFilterStateChanged(bool enabled)
|
void TransferListFiltersWidget::onCategoryFilterStateChanged(bool enabled)
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <QtContainerFwd>
|
#include <QtContainerFwd>
|
||||||
|
|
||||||
#include "base/bittorrent/infohash.h"
|
#include "base/bittorrent/infohash.h"
|
||||||
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/bittorrent/trackerentry.h"
|
#include "base/bittorrent/trackerentry.h"
|
||||||
#include "base/path.h"
|
#include "base/path.h"
|
||||||
|
|
||||||
|
@ -41,11 +42,6 @@ class QResizeEvent;
|
||||||
|
|
||||||
class TransferListWidget;
|
class TransferListWidget;
|
||||||
|
|
||||||
namespace BitTorrent
|
|
||||||
{
|
|
||||||
class Torrent;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Net
|
namespace Net
|
||||||
{
|
{
|
||||||
struct DownloadResult;
|
struct DownloadResult;
|
||||||
|
@ -107,14 +103,10 @@ public:
|
||||||
|
|
||||||
// Redefine addItem() to make sure the list stays sorted
|
// Redefine addItem() to make sure the list stays sorted
|
||||||
void addItem(const QString &tracker, const BitTorrent::TorrentID &id);
|
void addItem(const QString &tracker, const BitTorrent::TorrentID &id);
|
||||||
void removeItem(const QString &tracker, const BitTorrent::TorrentID &id);
|
void removeItem(const QString &trackerURL, const BitTorrent::TorrentID &id);
|
||||||
void changeTrackerless(bool trackerless, const BitTorrent::TorrentID &id);
|
void changeTrackerless(bool trackerless, const BitTorrent::TorrentID &id);
|
||||||
void setDownloadTrackerFavicon(bool value);
|
void setDownloadTrackerFavicon(bool value);
|
||||||
|
void handleTrackerEntriesUpdated(const QHash<BitTorrent::Torrent *, QHash<QString, BitTorrent::TrackerEntryUpdateInfo>> &updateInfos);
|
||||||
public slots:
|
|
||||||
void trackerSuccess(const BitTorrent::TorrentID &id, const QString &tracker);
|
|
||||||
void trackerError(const BitTorrent::TorrentID &id, const QString &tracker);
|
|
||||||
void trackerWarning(const BitTorrent::TorrentID &id, const QString &tracker);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleFavicoDownloadFinished(const Net::DownloadResult &result);
|
void handleFavicoDownloadFinished(const Net::DownloadResult &result);
|
||||||
|
@ -155,14 +147,7 @@ public slots:
|
||||||
void addTrackers(const BitTorrent::Torrent *torrent, const QVector<BitTorrent::TrackerEntry> &trackers);
|
void addTrackers(const BitTorrent::Torrent *torrent, const QVector<BitTorrent::TrackerEntry> &trackers);
|
||||||
void removeTrackers(const BitTorrent::Torrent *torrent, const QVector<BitTorrent::TrackerEntry> &trackers);
|
void removeTrackers(const BitTorrent::Torrent *torrent, const QVector<BitTorrent::TrackerEntry> &trackers);
|
||||||
void changeTrackerless(const BitTorrent::Torrent *torrent, bool trackerless);
|
void changeTrackerless(const BitTorrent::Torrent *torrent, bool trackerless);
|
||||||
void trackerSuccess(const BitTorrent::Torrent *torrent, const QString &tracker);
|
void trackerEntriesUpdated(const QHash<BitTorrent::Torrent *, QHash<QString, BitTorrent::TrackerEntryUpdateInfo>> &updateInfos);
|
||||||
void trackerWarning(const BitTorrent::Torrent *torrent, const QString &tracker);
|
|
||||||
void trackerError(const BitTorrent::Torrent *torrent, const QString &tracker);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void trackerSuccess(const BitTorrent::TorrentID &id, const QString &tracker);
|
|
||||||
void trackerError(const BitTorrent::TorrentID &id, const QString &tracker);
|
|
||||||
void trackerWarning(const BitTorrent::TorrentID &id, const QString &tracker);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onCategoryFilterStateChanged(bool enabled);
|
void onCategoryFilterStateChanged(bool enabled);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue