mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-14 16:57:55 +00:00
Improve "info hash" handling
Define "torrent ID" concept, which is either a SHA1 hash for torrents of version 1, or a SHA256 hash (truncated to SHA1 hash length) for torrents of version 2. Add support for native libtorrent2 info hashes.
This commit is contained in:
parent
4da4fb0676
commit
561b597031
@ -339,7 +339,8 @@ void Application::runExternalProgram(const BitTorrent::Torrent *torrent) const
|
||||
program.replace("%C", QString::number(torrent->filesCount()));
|
||||
program.replace("%Z", QString::number(torrent->totalSize()));
|
||||
program.replace("%T", torrent->currentTracker());
|
||||
program.replace("%I", torrent->hash().toString());
|
||||
// TODO: Update GUI/WebUI labels for this parameter to express its meaning more clearly
|
||||
program.replace("%I", torrent->id().toString());
|
||||
|
||||
Logger *logger = Logger::instance();
|
||||
logger->addMessage(tr("Torrent: %1, running external program, command: %2").arg(torrent->name(), program));
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "base/bittorrent/common.h"
|
||||
#include "base/bittorrent/infohash.h"
|
||||
|
||||
void FileSearcher::search(const BitTorrent::InfoHash &id, const QStringList &originalFileNames
|
||||
void FileSearcher::search(const BitTorrent::TorrentID &id, const QStringList &originalFileNames
|
||||
, const QString &completeSavePath, const QString &incompleteSavePath)
|
||||
{
|
||||
const auto findInDir = [](const QString &dirPath, QStringList &fileNames) -> bool
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class InfoHash;
|
||||
class TorrentID;
|
||||
}
|
||||
|
||||
class FileSearcher final : public QObject
|
||||
@ -44,9 +44,9 @@ public:
|
||||
FileSearcher() = default;
|
||||
|
||||
public slots:
|
||||
void search(const BitTorrent::InfoHash &id, const QStringList &originalFileNames
|
||||
void search(const BitTorrent::TorrentID &id, const QStringList &originalFileNames
|
||||
, const QString &completeSavePath, const QString &incompleteSavePath);
|
||||
|
||||
signals:
|
||||
void searchFinished(const BitTorrent::InfoHash &id, const QString &savePath, const QStringList &fileNames);
|
||||
void searchFinished(const BitTorrent::TorrentID &id, const QString &savePath, const QStringList &fileNames);
|
||||
};
|
||||
|
@ -28,14 +28,54 @@
|
||||
|
||||
#include "infohash.h"
|
||||
|
||||
const int InfoHashTypeId = qRegisterMetaType<BitTorrent::InfoHash>();
|
||||
const int TorrentIDTypeId = qRegisterMetaType<BitTorrent::TorrentID>();
|
||||
|
||||
BitTorrent::InfoHash BitTorrent::InfoHash::fromString(const QString &hashString)
|
||||
BitTorrent::InfoHash::InfoHash(const WrappedType &nativeHash)
|
||||
: m_valid {true}
|
||||
, m_nativeHash {nativeHash}
|
||||
{
|
||||
return {SHA1Hash::fromString(hashString)};
|
||||
}
|
||||
|
||||
uint BitTorrent::qHash(const BitTorrent::InfoHash &key, const uint seed)
|
||||
bool BitTorrent::InfoHash::isValid() const
|
||||
{
|
||||
return ::qHash(std::hash<InfoHash::UnderlyingType>()(key), seed);
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
BitTorrent::TorrentID BitTorrent::InfoHash::toTorrentID() const
|
||||
{
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
return m_nativeHash.get_best();
|
||||
#else
|
||||
return {m_nativeHash};
|
||||
#endif
|
||||
}
|
||||
|
||||
BitTorrent::InfoHash::operator WrappedType() const
|
||||
{
|
||||
return m_nativeHash;
|
||||
}
|
||||
|
||||
BitTorrent::TorrentID BitTorrent::TorrentID::fromString(const QString &hashString)
|
||||
{
|
||||
return {BaseType::fromString(hashString)};
|
||||
}
|
||||
|
||||
BitTorrent::TorrentID BitTorrent::TorrentID::fromInfoHash(const BitTorrent::InfoHash &infoHash)
|
||||
{
|
||||
return infoHash.toTorrentID();
|
||||
}
|
||||
|
||||
uint BitTorrent::qHash(const BitTorrent::TorrentID &key, const uint seed)
|
||||
{
|
||||
return ::qHash(std::hash<TorrentID::UnderlyingType>()(key), seed);
|
||||
}
|
||||
|
||||
bool BitTorrent::operator==(const BitTorrent::InfoHash &left, const BitTorrent::InfoHash &right)
|
||||
{
|
||||
return (static_cast<InfoHash::WrappedType>(left) == static_cast<InfoHash::WrappedType>(right));
|
||||
}
|
||||
|
||||
bool BitTorrent::operator!=(const BitTorrent::InfoHash &left, const BitTorrent::InfoHash &right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
@ -28,6 +28,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <libtorrent/version.hpp>
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
#include <libtorrent/info_hash.hpp>
|
||||
#endif
|
||||
|
||||
#include <QHash>
|
||||
#include <QMetaType>
|
||||
|
||||
@ -38,15 +43,45 @@ using SHA256Hash = Digest32<256>;
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class InfoHash : public SHA1Hash
|
||||
class InfoHash;
|
||||
|
||||
class TorrentID : public Digest32<160>
|
||||
{
|
||||
public:
|
||||
using SHA1Hash::SHA1Hash;
|
||||
using BaseType = Digest32<160>;
|
||||
using BaseType::BaseType;
|
||||
|
||||
static InfoHash fromString(const QString &hashString);
|
||||
static TorrentID fromString(const QString &hashString);
|
||||
static TorrentID fromInfoHash(const InfoHash &infoHash);
|
||||
};
|
||||
|
||||
uint qHash(const InfoHash &key, const uint seed);
|
||||
class InfoHash
|
||||
{
|
||||
public:
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
using WrappedType = lt::info_hash_t;
|
||||
#else
|
||||
using WrappedType = lt::sha1_hash;
|
||||
#endif
|
||||
|
||||
InfoHash() = default;
|
||||
InfoHash(const InfoHash &other) = default;
|
||||
InfoHash(const WrappedType &nativeHash);
|
||||
|
||||
bool isValid() const;
|
||||
TorrentID toTorrentID() const;
|
||||
|
||||
operator WrappedType() const;
|
||||
|
||||
private:
|
||||
bool m_valid = false;
|
||||
WrappedType m_nativeHash;
|
||||
};
|
||||
|
||||
uint qHash(const TorrentID &key, uint seed);
|
||||
|
||||
bool operator==(const InfoHash &left, const InfoHash &right);
|
||||
bool operator!=(const InfoHash &left, const InfoHash &right);
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(BitTorrent::InfoHash)
|
||||
Q_DECLARE_METATYPE(BitTorrent::TorrentID)
|
||||
|
@ -47,8 +47,8 @@ namespace
|
||||
// == 20 (SHA-1 length in bytes) * 2 (each byte maps to 2 hex characters)
|
||||
// 2. 32 chars Base32 encoded string
|
||||
// == 20 (SHA-1 length in bytes) * 1.6 (the efficiency of Base32 encoding)
|
||||
const int SHA1_HEX_SIZE = BitTorrent::InfoHash::length() * 2;
|
||||
const int SHA1_BASE32_SIZE = BitTorrent::InfoHash::length() * 1.6;
|
||||
const int SHA1_HEX_SIZE = SHA1Hash::length() * 2;
|
||||
const int SHA1_BASE32_SIZE = SHA1Hash::length() * 1.6;
|
||||
|
||||
return ((((string.size() == SHA1_HEX_SIZE))
|
||||
&& !string.contains(QRegularExpression(QLatin1String("[^0-9A-Fa-f]"))))
|
||||
@ -73,7 +73,13 @@ MagnetUri::MagnetUri(const QString &source)
|
||||
if (ec) return;
|
||||
|
||||
m_valid = true;
|
||||
m_hash = m_addTorrentParams.info_hash;
|
||||
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
m_infoHash = m_addTorrentParams.info_hashes;
|
||||
#else
|
||||
m_infoHash = m_addTorrentParams.info_hash;
|
||||
#endif
|
||||
|
||||
m_name = QString::fromStdString(m_addTorrentParams.name);
|
||||
|
||||
m_trackers.reserve(m_addTorrentParams.trackers.size());
|
||||
@ -90,9 +96,9 @@ bool MagnetUri::isValid() const
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
InfoHash MagnetUri::hash() const
|
||||
InfoHash MagnetUri::infoHash() const
|
||||
{
|
||||
return m_hash;
|
||||
return m_infoHash;
|
||||
}
|
||||
|
||||
QString MagnetUri::name() const
|
||||
|
@ -46,7 +46,7 @@ namespace BitTorrent
|
||||
explicit MagnetUri(const QString &source = {});
|
||||
|
||||
bool isValid() const;
|
||||
InfoHash hash() const;
|
||||
InfoHash infoHash() const;
|
||||
QString name() const;
|
||||
QVector<TrackerEntry> trackers() const;
|
||||
QVector<QUrl> urlSeeds() const;
|
||||
@ -57,7 +57,7 @@ namespace BitTorrent
|
||||
private:
|
||||
bool m_valid;
|
||||
QString m_url;
|
||||
InfoHash m_hash;
|
||||
InfoHash m_infoHash;
|
||||
QString m_name;
|
||||
QVector<TrackerEntry> m_trackers;
|
||||
QVector<QUrl> m_urlSeeds;
|
||||
|
@ -1616,7 +1616,7 @@ void Session::processShareLimits()
|
||||
|
||||
// We shouldn't iterate over `m_torrents` in the loop below
|
||||
// since `deleteTorrent()` modifies it indirectly
|
||||
const QHash<InfoHash, TorrentImpl *> torrents {m_torrents};
|
||||
const QHash<TorrentID, TorrentImpl *> torrents {m_torrents};
|
||||
for (TorrentImpl *const torrent : torrents)
|
||||
{
|
||||
if (torrent->isSeed() && !torrent->isForced())
|
||||
@ -1638,12 +1638,12 @@ void Session::processShareLimits()
|
||||
if (m_maxRatioAction == Remove)
|
||||
{
|
||||
LogMsg(tr("'%1' reached the maximum ratio you set. Removed.").arg(torrent->name()));
|
||||
deleteTorrent(torrent->hash());
|
||||
deleteTorrent(torrent->id());
|
||||
}
|
||||
else if (m_maxRatioAction == DeleteFiles)
|
||||
{
|
||||
LogMsg(tr("'%1' reached the maximum ratio you set. Removed torrent and its files.").arg(torrent->name()));
|
||||
deleteTorrent(torrent->hash(), DeleteTorrentAndFiles);
|
||||
deleteTorrent(torrent->id(), DeleteTorrentAndFiles);
|
||||
}
|
||||
else if ((m_maxRatioAction == Pause) && !torrent->isPaused())
|
||||
{
|
||||
@ -1677,12 +1677,12 @@ void Session::processShareLimits()
|
||||
if (m_maxRatioAction == Remove)
|
||||
{
|
||||
LogMsg(tr("'%1' reached the maximum seeding time you set. Removed.").arg(torrent->name()));
|
||||
deleteTorrent(torrent->hash());
|
||||
deleteTorrent(torrent->id());
|
||||
}
|
||||
else if (m_maxRatioAction == DeleteFiles)
|
||||
{
|
||||
LogMsg(tr("'%1' reached the maximum seeding time you set. Removed torrent and its files.").arg(torrent->name()));
|
||||
deleteTorrent(torrent->hash(), DeleteTorrentAndFiles);
|
||||
deleteTorrent(torrent->id(), DeleteTorrentAndFiles);
|
||||
}
|
||||
else if ((m_maxRatioAction == Pause) && !torrent->isPaused())
|
||||
{
|
||||
@ -1719,7 +1719,7 @@ void Session::handleDownloadFinished(const Net::DownloadResult &result)
|
||||
}
|
||||
}
|
||||
|
||||
void Session::fileSearchFinished(const InfoHash &id, const QString &savePath, const QStringList &fileNames)
|
||||
void Session::fileSearchFinished(const TorrentID &id, const QString &savePath, const QStringList &fileNames)
|
||||
{
|
||||
TorrentImpl *torrent = m_torrents.value(id);
|
||||
if (torrent)
|
||||
@ -1745,9 +1745,9 @@ void Session::fileSearchFinished(const InfoHash &id, const QString &savePath, co
|
||||
}
|
||||
|
||||
// Return the torrent handle, given its hash
|
||||
Torrent *Session::findTorrent(const InfoHash &hash) const
|
||||
Torrent *Session::findTorrent(const TorrentID &id) const
|
||||
{
|
||||
return m_torrents.value(hash);
|
||||
return m_torrents.value(id);
|
||||
}
|
||||
|
||||
bool Session::hasActiveTorrents() const
|
||||
@ -1795,18 +1795,18 @@ void Session::banIP(const QString &ip)
|
||||
|
||||
// Delete a torrent from the session, given its hash
|
||||
// and from the disk, if the corresponding deleteOption is chosen
|
||||
bool Session::deleteTorrent(const InfoHash &hash, const DeleteOption deleteOption)
|
||||
bool Session::deleteTorrent(const TorrentID &id, const DeleteOption deleteOption)
|
||||
{
|
||||
TorrentImpl *const torrent = m_torrents.take(hash);
|
||||
TorrentImpl *const torrent = m_torrents.take(id);
|
||||
if (!torrent) return false;
|
||||
|
||||
qDebug("Deleting torrent with hash: %s", qUtf8Printable(torrent->hash().toString()));
|
||||
qDebug("Deleting torrent with ID: %s", qUtf8Printable(torrent->id().toString()));
|
||||
emit torrentAboutToBeRemoved(torrent);
|
||||
|
||||
// Remove it from session
|
||||
if (deleteOption == DeleteTorrent)
|
||||
{
|
||||
m_removingTorrents[torrent->hash()] = {torrent->name(), "", deleteOption};
|
||||
m_removingTorrents[torrent->id()] = {torrent->name(), "", deleteOption};
|
||||
|
||||
const lt::torrent_handle nativeHandle {torrent->nativeHandle()};
|
||||
const auto iter = std::find_if(m_moveStorageQueue.begin(), m_moveStorageQueue.end()
|
||||
@ -1835,7 +1835,7 @@ bool Session::deleteTorrent(const InfoHash &hash, const DeleteOption deleteOptio
|
||||
rootPath = torrent->actualStorageLocation();
|
||||
}
|
||||
|
||||
m_removingTorrents[torrent->hash()] = {torrent->name(), rootPath, deleteOption};
|
||||
m_removingTorrents[torrent->id()] = {torrent->name(), rootPath, deleteOption};
|
||||
|
||||
if (m_moveStorageQueue.size() > 1)
|
||||
{
|
||||
@ -1854,8 +1854,8 @@ bool Session::deleteTorrent(const InfoHash &hash, const DeleteOption deleteOptio
|
||||
}
|
||||
|
||||
// Remove it from torrent resume directory
|
||||
const QString resumedataFile = QString::fromLatin1("%1.fastresume").arg(torrent->hash().toString());
|
||||
const QString metadataFile = QString::fromLatin1("%1.torrent").arg(torrent->hash().toString());
|
||||
const QString resumedataFile = QString::fromLatin1("%1.fastresume").arg(torrent->id().toString());
|
||||
const QString metadataFile = QString::fromLatin1("%1.torrent").arg(torrent->id().toString());
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
||||
QMetaObject::invokeMethod(m_resumeDataSavingManager, [this, resumedataFile, metadataFile]()
|
||||
{
|
||||
@ -1871,19 +1871,19 @@ bool Session::deleteTorrent(const InfoHash &hash, const DeleteOption deleteOptio
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Session::cancelDownloadMetadata(const InfoHash &hash)
|
||||
bool Session::cancelDownloadMetadata(const TorrentID &id)
|
||||
{
|
||||
const auto downloadedMetadataIter = m_downloadedMetadata.find(hash);
|
||||
const auto downloadedMetadataIter = m_downloadedMetadata.find(id);
|
||||
if (downloadedMetadataIter == m_downloadedMetadata.end()) return false;
|
||||
|
||||
m_downloadedMetadata.erase(downloadedMetadataIter);
|
||||
--m_extraLimit;
|
||||
adjustLimits();
|
||||
m_nativeSession->remove_torrent(m_nativeSession->find_torrent(hash), lt::session::delete_files);
|
||||
m_nativeSession->remove_torrent(m_nativeSession->find_torrent(id), lt::session::delete_files);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Session::increaseTorrentsQueuePos(const QVector<InfoHash> &hashes)
|
||||
void Session::increaseTorrentsQueuePos(const QVector<TorrentID> &ids)
|
||||
{
|
||||
using ElementType = std::pair<int, const TorrentImpl *>;
|
||||
std::priority_queue<ElementType
|
||||
@ -1891,9 +1891,9 @@ void Session::increaseTorrentsQueuePos(const QVector<InfoHash> &hashes)
|
||||
, std::greater<ElementType>> torrentQueue;
|
||||
|
||||
// Sort torrents by queue position
|
||||
for (const InfoHash &infoHash : hashes)
|
||||
for (const TorrentID &id : ids)
|
||||
{
|
||||
const TorrentImpl *torrent = m_torrents.value(infoHash);
|
||||
const TorrentImpl *torrent = m_torrents.value(id);
|
||||
if (!torrent) continue;
|
||||
if (const int position = torrent->queuePosition(); position >= 0)
|
||||
torrentQueue.emplace(position, torrent);
|
||||
@ -1910,15 +1910,15 @@ void Session::increaseTorrentsQueuePos(const QVector<InfoHash> &hashes)
|
||||
saveTorrentsQueue();
|
||||
}
|
||||
|
||||
void Session::decreaseTorrentsQueuePos(const QVector<InfoHash> &hashes)
|
||||
void Session::decreaseTorrentsQueuePos(const QVector<TorrentID> &ids)
|
||||
{
|
||||
using ElementType = std::pair<int, const TorrentImpl *>;
|
||||
std::priority_queue<ElementType> torrentQueue;
|
||||
|
||||
// Sort torrents by queue position
|
||||
for (const InfoHash &infoHash : hashes)
|
||||
for (const TorrentID &id : ids)
|
||||
{
|
||||
const TorrentImpl *torrent = m_torrents.value(infoHash);
|
||||
const TorrentImpl *torrent = m_torrents.value(id);
|
||||
if (!torrent) continue;
|
||||
if (const int position = torrent->queuePosition(); position >= 0)
|
||||
torrentQueue.emplace(position, torrent);
|
||||
@ -1938,15 +1938,15 @@ void Session::decreaseTorrentsQueuePos(const QVector<InfoHash> &hashes)
|
||||
saveTorrentsQueue();
|
||||
}
|
||||
|
||||
void Session::topTorrentsQueuePos(const QVector<InfoHash> &hashes)
|
||||
void Session::topTorrentsQueuePos(const QVector<TorrentID> &ids)
|
||||
{
|
||||
using ElementType = std::pair<int, const TorrentImpl *>;
|
||||
std::priority_queue<ElementType> torrentQueue;
|
||||
|
||||
// Sort torrents by queue position
|
||||
for (const InfoHash &infoHash : hashes)
|
||||
for (const TorrentID &id : ids)
|
||||
{
|
||||
const TorrentImpl *torrent = m_torrents.value(infoHash);
|
||||
const TorrentImpl *torrent = m_torrents.value(id);
|
||||
if (!torrent) continue;
|
||||
if (const int position = torrent->queuePosition(); position >= 0)
|
||||
torrentQueue.emplace(position, torrent);
|
||||
@ -1963,7 +1963,7 @@ void Session::topTorrentsQueuePos(const QVector<InfoHash> &hashes)
|
||||
saveTorrentsQueue();
|
||||
}
|
||||
|
||||
void Session::bottomTorrentsQueuePos(const QVector<InfoHash> &hashes)
|
||||
void Session::bottomTorrentsQueuePos(const QVector<TorrentID> &ids)
|
||||
{
|
||||
using ElementType = std::pair<int, const TorrentImpl *>;
|
||||
std::priority_queue<ElementType
|
||||
@ -1971,9 +1971,9 @@ void Session::bottomTorrentsQueuePos(const QVector<InfoHash> &hashes)
|
||||
, std::greater<ElementType>> torrentQueue;
|
||||
|
||||
// Sort torrents by queue position
|
||||
for (const InfoHash &infoHash : hashes)
|
||||
for (const TorrentID &id : ids)
|
||||
{
|
||||
const TorrentImpl *torrent = m_torrents.value(infoHash);
|
||||
const TorrentImpl *torrent = m_torrents.value(id);
|
||||
if (!torrent) continue;
|
||||
if (const int position = torrent->queuePosition(); position >= 0)
|
||||
torrentQueue.emplace(position, torrent);
|
||||
@ -2088,20 +2088,20 @@ bool Session::addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &source
|
||||
const bool hasMetadata = std::holds_alternative<TorrentInfo>(source);
|
||||
TorrentInfo metadata = (hasMetadata ? std::get<TorrentInfo>(source) : TorrentInfo {});
|
||||
const MagnetUri &magnetUri = (hasMetadata ? MagnetUri {} : std::get<MagnetUri>(source));
|
||||
const InfoHash hash = (hasMetadata ? metadata.hash() : magnetUri.hash());
|
||||
const auto id = TorrentID::fromInfoHash(hasMetadata ? metadata.infoHash() : magnetUri.infoHash());
|
||||
|
||||
// It looks illogical that we don't just use an existing handle,
|
||||
// but as previous experience has shown, it actually creates unnecessary
|
||||
// problems and unwanted behavior due to the fact that it was originally
|
||||
// added with parameters other than those provided by the user.
|
||||
cancelDownloadMetadata(hash);
|
||||
cancelDownloadMetadata(id);
|
||||
|
||||
// We should not add the torrent if it is already
|
||||
// processed or is pending to add to session
|
||||
if (m_loadingTorrents.contains(hash))
|
||||
if (m_loadingTorrents.contains(id))
|
||||
return false;
|
||||
|
||||
TorrentImpl *const torrent = m_torrents.value(hash);
|
||||
TorrentImpl *const torrent = m_torrents.value(id);
|
||||
if (torrent)
|
||||
{ // a duplicate torrent is added
|
||||
if (torrent->isPrivate() || (hasMetadata && metadata.isPrivate()))
|
||||
@ -2192,7 +2192,7 @@ bool Session::addTorrent_impl(const std::variant<MagnetUri, TorrentInfo> &source
|
||||
if (!isFindingIncompleteFiles)
|
||||
return loadTorrent(loadTorrentParams);
|
||||
|
||||
m_loadingTorrents.insert(hash, loadTorrentParams);
|
||||
m_loadingTorrents.insert(id, loadTorrentParams);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2209,8 +2209,12 @@ bool Session::loadTorrent(LoadTorrentParams params)
|
||||
p.max_uploads = maxUploadsPerTorrent();
|
||||
|
||||
const bool hasMetadata = (p.ti && p.ti->is_valid());
|
||||
const InfoHash hash = (hasMetadata ? p.ti->info_hash() : p.info_hash);
|
||||
m_loadingTorrents.insert(hash, params);
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
const auto id = TorrentID::fromInfoHash(hasMetadata ? p.ti->info_hashes() : p.info_hashes);
|
||||
#else
|
||||
const auto id = TorrentID::fromInfoHash(hasMetadata ? p.ti->info_hash() : p.info_hash);
|
||||
#endif
|
||||
m_loadingTorrents.insert(id, params);
|
||||
|
||||
// Adding torrent to BitTorrent session
|
||||
m_nativeSession->async_add_torrent(p);
|
||||
@ -2220,7 +2224,7 @@ bool Session::loadTorrent(LoadTorrentParams params)
|
||||
|
||||
void Session::findIncompleteFiles(const TorrentInfo &torrentInfo, const QString &savePath) const
|
||||
{
|
||||
const InfoHash searchId = torrentInfo.hash();
|
||||
const auto searchId = TorrentID::fromInfoHash(torrentInfo.infoHash());
|
||||
const QStringList originalFileNames = torrentInfo.filePaths();
|
||||
const QString completeSavePath = savePath;
|
||||
const QString incompleteSavePath = (isTempPathEnabled() ? torrentTempPath(torrentInfo) : QString {});
|
||||
@ -2231,7 +2235,7 @@ void Session::findIncompleteFiles(const TorrentInfo &torrentInfo, const QString
|
||||
});
|
||||
#else
|
||||
QMetaObject::invokeMethod(m_fileSearcher, "search"
|
||||
, Q_ARG(BitTorrent::InfoHash, searchId), Q_ARG(QStringList, originalFileNames)
|
||||
, Q_ARG(BitTorrent::TorrentID, searchId), Q_ARG(QStringList, originalFileNames)
|
||||
, Q_ARG(QString, completeSavePath), Q_ARG(QString, incompleteSavePath));
|
||||
#endif
|
||||
}
|
||||
@ -2242,17 +2246,17 @@ bool Session::downloadMetadata(const MagnetUri &magnetUri)
|
||||
{
|
||||
if (!magnetUri.isValid()) return false;
|
||||
|
||||
const InfoHash hash = magnetUri.hash();
|
||||
const auto id = TorrentID::fromInfoHash(magnetUri.infoHash());
|
||||
const QString name = magnetUri.name();
|
||||
|
||||
// We should not add torrent if it's already
|
||||
// processed or adding to session
|
||||
if (m_torrents.contains(hash)) return false;
|
||||
if (m_loadingTorrents.contains(hash)) return false;
|
||||
if (m_downloadedMetadata.contains(hash)) return false;
|
||||
if (m_torrents.contains(id)) return false;
|
||||
if (m_loadingTorrents.contains(id)) return false;
|
||||
if (m_downloadedMetadata.contains(id)) return false;
|
||||
|
||||
qDebug("Adding torrent to preload metadata...");
|
||||
qDebug(" -> Hash: %s", qUtf8Printable(hash.toString()));
|
||||
qDebug(" -> Torrent ID: %s", qUtf8Printable(id.toString()));
|
||||
qDebug(" -> Name: %s", qUtf8Printable(name));
|
||||
|
||||
lt::add_torrent_params p = magnetUri.addTorrentParams();
|
||||
@ -2268,7 +2272,7 @@ bool Session::downloadMetadata(const MagnetUri &magnetUri)
|
||||
p.max_connections = maxConnectionsPerTorrent();
|
||||
p.max_uploads = maxUploadsPerTorrent();
|
||||
|
||||
const QString savePath = Utils::Fs::tempPath() + hash.toString();
|
||||
const QString savePath = Utils::Fs::tempPath() + id.toString();
|
||||
p.save_path = Utils::Fs::toNativePath(savePath).toStdString();
|
||||
|
||||
// Forced start
|
||||
@ -2301,7 +2305,7 @@ void Session::exportTorrentFile(const Torrent *torrent, TorrentExportFolder fold
|
||||
((folder == TorrentExportFolder::Finished) && !finishedTorrentExportDirectory().isEmpty()));
|
||||
|
||||
const QString validName = Utils::Fs::toValidFileSystemName(torrent->name());
|
||||
const QString torrentFilename = QString::fromLatin1("%1.torrent").arg(torrent->hash().toString());
|
||||
const QString torrentFilename = QString::fromLatin1("%1.torrent").arg(torrent->id().toString());
|
||||
QString torrentExportFilename = QString::fromLatin1("%1.torrent").arg(validName);
|
||||
const QString torrentPath = QDir(m_resumeFolderPath).absoluteFilePath(torrentFilename);
|
||||
const QDir exportPath(folder == TorrentExportFolder::Regular ? torrentExportDirectory() : finishedTorrentExportDirectory());
|
||||
@ -2374,13 +2378,13 @@ void Session::saveTorrentsQueue() const
|
||||
// We require actual (non-cached) queue position here!
|
||||
const int queuePos = static_cast<LTUnderlyingType<lt::queue_position_t>>(torrent->nativeHandle().queue_position());
|
||||
if (queuePos >= 0)
|
||||
queue[queuePos] = torrent->hash().toString();
|
||||
queue[queuePos] = torrent->id().toString();
|
||||
}
|
||||
|
||||
QByteArray data;
|
||||
data.reserve(((InfoHash::length() * 2) + 1) * queue.size());
|
||||
for (const QString &hash : asConst(queue))
|
||||
data += (hash.toLatin1() + '\n');
|
||||
data.reserve(((TorrentID::length() * 2) + 1) * queue.size());
|
||||
for (const QString &torrentID : asConst(queue))
|
||||
data += (torrentID.toLatin1() + '\n');
|
||||
|
||||
const QString filename = QLatin1String {"queue"};
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
||||
@ -3758,11 +3762,11 @@ void Session::setMaxRatioAction(const MaxRatioAction act)
|
||||
|
||||
// If this functions returns true, we cannot add torrent to session,
|
||||
// but it is still possible to merge trackers in some cases
|
||||
bool Session::isKnownTorrent(const InfoHash &hash) const
|
||||
bool Session::isKnownTorrent(const TorrentID &id) const
|
||||
{
|
||||
return (m_torrents.contains(hash)
|
||||
|| m_loadingTorrents.contains(hash)
|
||||
|| m_downloadedMetadata.contains(hash));
|
||||
return (m_torrents.contains(id)
|
||||
|| m_loadingTorrents.contains(id)
|
||||
|| m_downloadedMetadata.contains(id));
|
||||
}
|
||||
|
||||
void Session::updateSeedingLimitTimer()
|
||||
@ -3868,7 +3872,7 @@ void Session::handleTorrentMetadataReceived(TorrentImpl *const torrent)
|
||||
{
|
||||
// Save metadata
|
||||
const QDir resumeDataDir {m_resumeFolderPath};
|
||||
const QString torrentFileName {QString {"%1.torrent"}.arg(torrent->hash().toString())};
|
||||
const QString torrentFileName {QString {"%1.torrent"}.arg(torrent->id().toString())};
|
||||
try
|
||||
{
|
||||
torrent->info().saveToFile(resumeDataDir.absoluteFilePath(torrentFileName));
|
||||
@ -3948,7 +3952,7 @@ void Session::handleTorrentResumeDataReady(TorrentImpl *const torrent, const std
|
||||
// Separated thread is used for the blocking IO which results in slow processing of many torrents.
|
||||
// Copying lt::entry objects around isn't cheap.
|
||||
|
||||
const QString filename = QString::fromLatin1("%1.fastresume").arg(torrent->hash().toString());
|
||||
const QString filename = QString::fromLatin1("%1.fastresume").arg(torrent->id().toString());
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
||||
QMetaObject::invokeMethod(m_resumeDataSavingManager
|
||||
, [this, filename, data]() { m_resumeDataSavingManager->save(filename, data); });
|
||||
@ -4024,9 +4028,13 @@ bool Session::addMoveTorrentStorageJob(TorrentImpl *torrent, const QString &newP
|
||||
|
||||
void Session::moveTorrentStorage(const MoveStorageJob &job) const
|
||||
{
|
||||
const InfoHash infoHash = job.torrentHandle.info_hash();
|
||||
const TorrentImpl *torrent = m_torrents.value(infoHash);
|
||||
const QString torrentName = (torrent ? torrent->name() : infoHash.toString());
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
const auto id = TorrentID::fromInfoHash(job.torrentHandle.info_hashes());
|
||||
#else
|
||||
const auto id = TorrentID::fromInfoHash(job.torrentHandle.info_hash());
|
||||
#endif
|
||||
const TorrentImpl *torrent = m_torrents.value(id);
|
||||
const QString torrentName = (torrent ? torrent->name() : id.toString());
|
||||
LogMsg(tr("Moving \"%1\" to \"%2\"...").arg(torrentName, job.path));
|
||||
|
||||
job.torrentHandle.move_storage(job.path.toUtf8().constData()
|
||||
@ -4157,9 +4165,9 @@ void Session::disableIPFilter()
|
||||
m_nativeSession->set_ip_filter(filter);
|
||||
}
|
||||
|
||||
void Session::recursiveTorrentDownload(const InfoHash &hash)
|
||||
void Session::recursiveTorrentDownload(const TorrentID &id)
|
||||
{
|
||||
TorrentImpl *const torrent = m_torrents.value(hash);
|
||||
TorrentImpl *const torrent = m_torrents.value(id);
|
||||
if (!torrent) return;
|
||||
|
||||
for (int i = 0; i < torrent->filesCount(); ++i)
|
||||
@ -4584,7 +4592,7 @@ void Session::createTorrent(const lt::torrent_handle &nativeHandle)
|
||||
const LoadTorrentParams params = m_loadingTorrents.take(nativeHandle.info_hash());
|
||||
|
||||
auto *const torrent = new TorrentImpl {this, m_nativeSession, nativeHandle, params};
|
||||
m_torrents.insert(torrent->hash(), torrent);
|
||||
m_torrents.insert(torrent->id(), torrent);
|
||||
|
||||
const bool hasMetadata = torrent->hasMetadata();
|
||||
|
||||
@ -4599,7 +4607,7 @@ void Session::createTorrent(const lt::torrent_handle &nativeHandle)
|
||||
{
|
||||
// Backup torrent file
|
||||
const QDir resumeDataDir {m_resumeFolderPath};
|
||||
const QString torrentFileName {QString::fromLatin1("%1.torrent").arg(torrent->hash().toString())};
|
||||
const QString torrentFileName {QString::fromLatin1("%1.torrent").arg(torrent->id().toString())};
|
||||
try
|
||||
{
|
||||
torrent->info().saveToFile(resumeDataDir.absoluteFilePath(torrentFileName));
|
||||
@ -4657,9 +4665,13 @@ void Session::handleAddTorrentAlert(const lt::add_torrent_alert *p)
|
||||
|
||||
void Session::handleTorrentRemovedAlert(const lt::torrent_removed_alert *p)
|
||||
{
|
||||
const InfoHash infoHash {p->info_hash};
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
const auto id = TorrentID::fromInfoHash(p->info_hashes);
|
||||
#else
|
||||
const auto id = TorrentID::fromInfoHash(p->info_hash);
|
||||
#endif
|
||||
|
||||
const auto removingTorrentDataIter = m_removingTorrents.find(infoHash);
|
||||
const auto removingTorrentDataIter = m_removingTorrents.find(id);
|
||||
if (removingTorrentDataIter != m_removingTorrents.end())
|
||||
{
|
||||
if (removingTorrentDataIter->deleteOption == DeleteTorrent)
|
||||
@ -4672,8 +4684,13 @@ void Session::handleTorrentRemovedAlert(const lt::torrent_removed_alert *p)
|
||||
|
||||
void Session::handleTorrentDeletedAlert(const lt::torrent_deleted_alert *p)
|
||||
{
|
||||
const InfoHash infoHash {p->info_hash};
|
||||
const auto removingTorrentDataIter = m_removingTorrents.find(infoHash);
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
const auto id = TorrentID::fromInfoHash(p->info_hashes);
|
||||
#else
|
||||
const auto id = TorrentID::fromInfoHash(p->info_hash);
|
||||
#endif
|
||||
|
||||
const auto removingTorrentDataIter = m_removingTorrents.find(id);
|
||||
|
||||
if (removingTorrentDataIter == m_removingTorrents.end())
|
||||
return;
|
||||
@ -4685,8 +4702,13 @@ void Session::handleTorrentDeletedAlert(const lt::torrent_deleted_alert *p)
|
||||
|
||||
void Session::handleTorrentDeleteFailedAlert(const lt::torrent_delete_failed_alert *p)
|
||||
{
|
||||
const InfoHash infoHash {p->info_hash};
|
||||
const auto removingTorrentDataIter = m_removingTorrents.find(infoHash);
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
const auto id = TorrentID::fromInfoHash(p->info_hashes);
|
||||
#else
|
||||
const auto id = TorrentID::fromInfoHash(p->info_hash);
|
||||
#endif
|
||||
|
||||
const auto removingTorrentDataIter = m_removingTorrents.find(id);
|
||||
|
||||
if (removingTorrentDataIter == m_removingTorrents.end())
|
||||
return;
|
||||
@ -4710,8 +4732,13 @@ void Session::handleTorrentDeleteFailedAlert(const lt::torrent_delete_failed_ale
|
||||
|
||||
void Session::handleMetadataReceivedAlert(const lt::metadata_received_alert *p)
|
||||
{
|
||||
const InfoHash hash {p->handle.info_hash()};
|
||||
const auto downloadedMetadataIter = m_downloadedMetadata.find(hash);
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
const auto id = TorrentID::fromInfoHash(p->handle.info_hashes());
|
||||
#else
|
||||
const auto id = TorrentID::fromInfoHash(p->handle.info_hash());
|
||||
#endif
|
||||
|
||||
const auto downloadedMetadataIter = m_downloadedMetadata.find(id);
|
||||
|
||||
if (downloadedMetadataIter != m_downloadedMetadata.end())
|
||||
{
|
||||
@ -4732,11 +4759,11 @@ void Session::handleFileErrorAlert(const lt::file_error_alert *p)
|
||||
if (!torrent)
|
||||
return;
|
||||
|
||||
const InfoHash hash = torrent->hash();
|
||||
const TorrentID id = torrent->id();
|
||||
|
||||
if (!m_recentErroredTorrents.contains(hash))
|
||||
if (!m_recentErroredTorrents.contains(id))
|
||||
{
|
||||
m_recentErroredTorrents.insert(hash);
|
||||
m_recentErroredTorrents.insert(id);
|
||||
|
||||
const QString msg = QString::fromStdString(p->message());
|
||||
LogMsg(tr("File error alert. Torrent: \"%1\". File: \"%2\". Reason: %3")
|
||||
@ -4935,9 +4962,14 @@ void Session::handleStorageMovedAlert(const lt::storage_moved_alert *p)
|
||||
const QString newPath {p->storage_path()};
|
||||
Q_ASSERT(newPath == currentJob.path);
|
||||
|
||||
const InfoHash infoHash = currentJob.torrentHandle.info_hash();
|
||||
TorrentImpl *torrent = m_torrents.value(infoHash);
|
||||
const QString torrentName = (torrent ? torrent->name() : infoHash.toString());
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
const auto id = TorrentID::fromInfoHash(currentJob.torrentHandle.info_hashes());
|
||||
#else
|
||||
const auto id = TorrentID::fromInfoHash(currentJob.torrentHandle.info_hash());
|
||||
#endif
|
||||
|
||||
TorrentImpl *torrent = m_torrents.value(id);
|
||||
const QString torrentName = (torrent ? torrent->name() : id.toString());
|
||||
LogMsg(tr("\"%1\" is successfully moved to \"%2\".").arg(torrentName, newPath));
|
||||
|
||||
handleMoveTorrentStorageJobFinished();
|
||||
@ -4950,9 +4982,14 @@ void Session::handleStorageMovedFailedAlert(const lt::storage_moved_failed_alert
|
||||
const MoveStorageJob ¤tJob = m_moveStorageQueue.first();
|
||||
Q_ASSERT(currentJob.torrentHandle == p->handle);
|
||||
|
||||
const InfoHash infoHash = currentJob.torrentHandle.info_hash();
|
||||
TorrentImpl *torrent = m_torrents.value(infoHash);
|
||||
const QString torrentName = (torrent ? torrent->name() : infoHash.toString());
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
const auto id = TorrentID::fromInfoHash(currentJob.torrentHandle.info_hashes());
|
||||
#else
|
||||
const auto id = TorrentID::fromInfoHash(currentJob.torrentHandle.info_hash());
|
||||
#endif
|
||||
|
||||
TorrentImpl *torrent = m_torrents.value(id);
|
||||
const QString torrentName = (torrent ? torrent->name() : id.toString());
|
||||
const QString currentLocation = QString::fromStdString(p->handle.status(lt::torrent_handle::query_save_path).save_path);
|
||||
const QString errorMessage = QString::fromStdString(p->message());
|
||||
LogMsg(tr("Failed to move \"%1\" from \"%2\" to \"%3\". Reason: %4.")
|
||||
@ -4968,8 +5005,12 @@ void Session::handleStateUpdateAlert(const lt::state_update_alert *p)
|
||||
|
||||
for (const lt::torrent_status &status : p->status)
|
||||
{
|
||||
TorrentImpl *const torrent = m_torrents.value(status.info_hash);
|
||||
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
const auto id = TorrentID::fromInfoHash(status.info_hashes);
|
||||
#else
|
||||
const auto id = TorrentID::fromInfoHash(status.info_hash);
|
||||
#endif
|
||||
TorrentImpl *const torrent = m_torrents.value(id);
|
||||
if (!torrent)
|
||||
continue;
|
||||
|
||||
|
@ -434,7 +434,7 @@ namespace BitTorrent
|
||||
#endif
|
||||
|
||||
void startUpTorrents();
|
||||
Torrent *findTorrent(const InfoHash &hash) const;
|
||||
Torrent *findTorrent(const TorrentID &id) const;
|
||||
QVector<Torrent *> torrents() const;
|
||||
bool hasActiveTorrents() const;
|
||||
bool hasUnfinishedTorrents() const;
|
||||
@ -450,19 +450,19 @@ namespace BitTorrent
|
||||
|
||||
void banIP(const QString &ip);
|
||||
|
||||
bool isKnownTorrent(const InfoHash &hash) const;
|
||||
bool isKnownTorrent(const TorrentID &id) const;
|
||||
bool addTorrent(const QString &source, const AddTorrentParams ¶ms = AddTorrentParams());
|
||||
bool addTorrent(const MagnetUri &magnetUri, const AddTorrentParams ¶ms = AddTorrentParams());
|
||||
bool addTorrent(const TorrentInfo &torrentInfo, const AddTorrentParams ¶ms = AddTorrentParams());
|
||||
bool deleteTorrent(const InfoHash &hash, DeleteOption deleteOption = DeleteTorrent);
|
||||
bool deleteTorrent(const TorrentID &id, DeleteOption deleteOption = DeleteTorrent);
|
||||
bool downloadMetadata(const MagnetUri &magnetUri);
|
||||
bool cancelDownloadMetadata(const InfoHash &hash);
|
||||
bool cancelDownloadMetadata(const TorrentID &id);
|
||||
|
||||
void recursiveTorrentDownload(const InfoHash &hash);
|
||||
void increaseTorrentsQueuePos(const QVector<InfoHash> &hashes);
|
||||
void decreaseTorrentsQueuePos(const QVector<InfoHash> &hashes);
|
||||
void topTorrentsQueuePos(const QVector<InfoHash> &hashes);
|
||||
void bottomTorrentsQueuePos(const QVector<InfoHash> &hashes);
|
||||
void recursiveTorrentDownload(const TorrentID &id);
|
||||
void increaseTorrentsQueuePos(const QVector<TorrentID> &ids);
|
||||
void decreaseTorrentsQueuePos(const QVector<TorrentID> &ids);
|
||||
void topTorrentsQueuePos(const QVector<TorrentID> &ids);
|
||||
void bottomTorrentsQueuePos(const QVector<TorrentID> &ids);
|
||||
|
||||
// Torrent interface
|
||||
void handleTorrentSaveResumeDataRequested(const TorrentImpl *torrent);
|
||||
@ -539,7 +539,7 @@ namespace BitTorrent
|
||||
void handleIPFilterParsed(int ruleCount);
|
||||
void handleIPFilterError();
|
||||
void handleDownloadFinished(const Net::DownloadResult &result);
|
||||
void fileSearchFinished(const InfoHash &id, const QString &savePath, const QStringList &fileNames);
|
||||
void fileSearchFinished(const TorrentID &id, const QString &savePath, const QStringList &fileNames);
|
||||
|
||||
// Session reconfiguration triggers
|
||||
void networkOnlineStateChanged(bool online);
|
||||
@ -764,17 +764,17 @@ namespace BitTorrent
|
||||
ResumeDataSavingManager *m_resumeDataSavingManager = nullptr;
|
||||
FileSearcher *m_fileSearcher = nullptr;
|
||||
|
||||
QSet<InfoHash> m_downloadedMetadata;
|
||||
QSet<TorrentID> m_downloadedMetadata;
|
||||
|
||||
QHash<InfoHash, TorrentImpl *> m_torrents;
|
||||
QHash<InfoHash, LoadTorrentParams> m_loadingTorrents;
|
||||
QHash<TorrentID, TorrentImpl *> m_torrents;
|
||||
QHash<TorrentID, LoadTorrentParams> m_loadingTorrents;
|
||||
QHash<QString, AddTorrentParams> m_downloadedTorrents;
|
||||
QHash<InfoHash, RemovingTorrentData> m_removingTorrents;
|
||||
QHash<TorrentID, RemovingTorrentData> m_removingTorrents;
|
||||
QStringMap m_categories;
|
||||
QSet<QString> m_tags;
|
||||
|
||||
// I/O errored torrents
|
||||
QSet<InfoHash> m_recentErroredTorrents;
|
||||
QSet<TorrentID> m_recentErroredTorrents;
|
||||
QTimer *m_recentErroredTorrentsTimer = nullptr;
|
||||
|
||||
SessionMetricIndices m_metricIndices;
|
||||
|
@ -31,6 +31,8 @@
|
||||
|
||||
#include <QHash>
|
||||
|
||||
#include "infohash.h"
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
uint qHash(const TorrentState key, const uint seed)
|
||||
@ -49,6 +51,11 @@ namespace BitTorrent
|
||||
const qreal Torrent::MAX_RATIO = 9999;
|
||||
const int Torrent::MAX_SEEDING_TIME = 525600;
|
||||
|
||||
TorrentID Torrent::id() const
|
||||
{
|
||||
return infoHash().toTorrentID();
|
||||
}
|
||||
|
||||
bool Torrent::isResumed() const
|
||||
{
|
||||
return !isPaused();
|
||||
|
@ -44,6 +44,7 @@ namespace BitTorrent
|
||||
enum class DownloadPriority;
|
||||
class InfoHash;
|
||||
class PeerInfo;
|
||||
class TorrentID;
|
||||
class TorrentInfo;
|
||||
struct PeerAddress;
|
||||
struct TrackerEntry;
|
||||
@ -105,7 +106,7 @@ namespace BitTorrent
|
||||
|
||||
virtual ~Torrent() = default;
|
||||
|
||||
virtual InfoHash hash() const = 0;
|
||||
virtual InfoHash infoHash() const = 0;
|
||||
virtual QString name() const = 0;
|
||||
virtual QDateTime creationDate() const = 0;
|
||||
virtual QString creator() const = 0;
|
||||
@ -290,6 +291,7 @@ namespace BitTorrent
|
||||
|
||||
virtual QString createMagnetURI() const = 0;
|
||||
|
||||
TorrentID id() const;
|
||||
bool isResumed() const;
|
||||
qlonglong remainingSize() const;
|
||||
|
||||
|
@ -218,6 +218,11 @@ TorrentImpl::TorrentImpl(Session *session, lt::session *nativeSession
|
||||
, m_session(session)
|
||||
, m_nativeSession(nativeSession)
|
||||
, m_nativeHandle(nativeHandle)
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
, m_infoHash(m_nativeHandle.info_hashes())
|
||||
#else
|
||||
, m_infoHash(m_nativeHandle.info_hash())
|
||||
#endif
|
||||
, m_name(params.name)
|
||||
, m_savePath(Utils::Fs::toNativePath(params.savePath))
|
||||
, m_category(params.category)
|
||||
@ -235,7 +240,6 @@ TorrentImpl::TorrentImpl(Session *session, lt::session *nativeSession
|
||||
if (m_useAutoTMM)
|
||||
m_savePath = Utils::Fs::toNativePath(m_session->categorySavePath(m_category));
|
||||
|
||||
m_hash = InfoHash {m_nativeHandle.info_hash()};
|
||||
if (m_ltAddTorrentParams.ti)
|
||||
{
|
||||
// Initialize it only if torrent is added with metadata.
|
||||
@ -280,9 +284,9 @@ bool TorrentImpl::isValid() const
|
||||
return m_nativeHandle.is_valid();
|
||||
}
|
||||
|
||||
InfoHash TorrentImpl::hash() const
|
||||
InfoHash TorrentImpl::infoHash() const
|
||||
{
|
||||
return m_hash;
|
||||
return m_infoHash;
|
||||
}
|
||||
|
||||
QString TorrentImpl::name() const
|
||||
@ -297,7 +301,7 @@ QString TorrentImpl::name() const
|
||||
if (!name.isEmpty())
|
||||
return name;
|
||||
|
||||
return m_hash.toString();
|
||||
return id().toString();
|
||||
}
|
||||
|
||||
QDateTime TorrentImpl::creationDate() const
|
||||
|
@ -99,7 +99,7 @@ namespace BitTorrent
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
InfoHash hash() const override;
|
||||
InfoHash infoHash() const override;
|
||||
QString name() const override;
|
||||
QDateTime creationDate() const override;
|
||||
QString creator() const override;
|
||||
@ -301,7 +301,7 @@ namespace BitTorrent
|
||||
TorrentInfo m_torrentInfo;
|
||||
SpeedMonitor m_speedMonitor;
|
||||
|
||||
InfoHash m_hash;
|
||||
InfoHash m_infoHash;
|
||||
|
||||
// m_moveFinishedTriggers is activated only when the following conditions are met:
|
||||
// all file rename jobs complete, all file move jobs complete
|
||||
|
@ -184,10 +184,15 @@ bool TorrentInfo::isValid() const
|
||||
return (m_nativeInfo && m_nativeInfo->is_valid() && (m_nativeInfo->num_files() > 0));
|
||||
}
|
||||
|
||||
InfoHash TorrentInfo::hash() const
|
||||
InfoHash TorrentInfo::infoHash() const
|
||||
{
|
||||
if (!isValid()) return {};
|
||||
|
||||
#if (LIBTORRENT_VERSION_NUM >= 20000)
|
||||
return m_nativeInfo->info_hashes();
|
||||
#else
|
||||
return m_nativeInfo->info_hash();
|
||||
#endif
|
||||
}
|
||||
|
||||
QString TorrentInfo::name() const
|
||||
@ -374,7 +379,7 @@ QVector<QByteArray> TorrentInfo::pieceHashes() const
|
||||
hashes.reserve(count);
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
hashes += {m_nativeInfo->hash_for_piece_ptr(lt::piece_index_t {i}), InfoHash::length()};
|
||||
hashes += {m_nativeInfo->hash_for_piece_ptr(lt::piece_index_t {i}), SHA1Hash::length()};
|
||||
|
||||
return hashes;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ namespace BitTorrent
|
||||
TorrentInfo &operator=(const TorrentInfo &other);
|
||||
|
||||
bool isValid() const;
|
||||
InfoHash hash() const;
|
||||
InfoHash infoHash() const;
|
||||
QString name() const;
|
||||
QDateTime creationDate() const;
|
||||
QString creator() const;
|
||||
|
@ -153,7 +153,7 @@ struct Tracker::TrackerAnnounceRequest
|
||||
{
|
||||
QHostAddress socketAddress;
|
||||
QByteArray claimedAddress; // self claimed by peer
|
||||
InfoHash infoHash;
|
||||
TorrentID torrentID;
|
||||
QString event;
|
||||
Peer peer;
|
||||
int numwant = 50;
|
||||
@ -295,11 +295,11 @@ void Tracker::processAnnounceRequest()
|
||||
if (infoHashIter == queryParams.end())
|
||||
throw TrackerError("Missing \"info_hash\" parameter");
|
||||
|
||||
const auto infoHash = InfoHash::fromString(infoHashIter->toHex());
|
||||
if (!infoHash.isValid())
|
||||
const auto torrentID = TorrentID::fromString(infoHashIter->toHex());
|
||||
if (!torrentID.isValid())
|
||||
throw TrackerError("Invalid \"info_hash\" parameter");
|
||||
|
||||
announceReq.infoHash = infoHash;
|
||||
announceReq.torrentID = torrentID;
|
||||
|
||||
// 2. peer_id
|
||||
const auto peerIdIter = queryParams.find(ANNOUNCE_REQUEST_PEER_ID);
|
||||
@ -381,19 +381,19 @@ void Tracker::processAnnounceRequest()
|
||||
|
||||
void Tracker::registerPeer(const TrackerAnnounceRequest &announceReq)
|
||||
{
|
||||
if (!m_torrents.contains(announceReq.infoHash))
|
||||
if (!m_torrents.contains(announceReq.torrentID))
|
||||
{
|
||||
// Reached max size, remove a random torrent
|
||||
if (m_torrents.size() >= MAX_TORRENTS)
|
||||
m_torrents.erase(m_torrents.begin());
|
||||
}
|
||||
|
||||
m_torrents[announceReq.infoHash].setPeer(announceReq.peer);
|
||||
m_torrents[announceReq.torrentID].setPeer(announceReq.peer);
|
||||
}
|
||||
|
||||
void Tracker::unregisterPeer(const TrackerAnnounceRequest &announceReq)
|
||||
{
|
||||
const auto torrentStatsIter = m_torrents.find(announceReq.infoHash);
|
||||
const auto torrentStatsIter = m_torrents.find(announceReq.torrentID);
|
||||
if (torrentStatsIter == m_torrents.end())
|
||||
return;
|
||||
|
||||
@ -405,7 +405,7 @@ void Tracker::unregisterPeer(const TrackerAnnounceRequest &announceReq)
|
||||
|
||||
void Tracker::prepareAnnounceResponse(const TrackerAnnounceRequest &announceReq)
|
||||
{
|
||||
const TorrentStats &torrentStats = m_torrents[announceReq.infoHash];
|
||||
const TorrentStats &torrentStats = m_torrents[announceReq.torrentID];
|
||||
|
||||
lt::entry::dictionary_type replyDict
|
||||
{
|
||||
|
@ -102,6 +102,6 @@ namespace BitTorrent
|
||||
Http::Request m_request;
|
||||
Http::Environment m_env;
|
||||
|
||||
QHash<InfoHash, TorrentStats> m_torrents;
|
||||
QHash<TorrentID, TorrentStats> m_torrents;
|
||||
};
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "bittorrent/torrent.h"
|
||||
|
||||
const QString TorrentFilter::AnyCategory;
|
||||
const InfoHashSet TorrentFilter::AnyHash {{}};
|
||||
const TorrentIDSet TorrentFilter::AnyID {{}};
|
||||
const QString TorrentFilter::AnyTag;
|
||||
|
||||
const TorrentFilter TorrentFilter::DownloadingTorrent(TorrentFilter::Downloading);
|
||||
@ -49,19 +49,19 @@ const TorrentFilter TorrentFilter::ErroredTorrent(TorrentFilter::Errored);
|
||||
|
||||
using BitTorrent::Torrent;
|
||||
|
||||
TorrentFilter::TorrentFilter(const Type type, const InfoHashSet &hashSet, const QString &category, const QString &tag)
|
||||
TorrentFilter::TorrentFilter(const Type type, const TorrentIDSet &idSet, const QString &category, const QString &tag)
|
||||
: m_type(type)
|
||||
, m_category(category)
|
||||
, m_tag(tag)
|
||||
, m_hashSet(hashSet)
|
||||
, m_idSet(idSet)
|
||||
{
|
||||
}
|
||||
|
||||
TorrentFilter::TorrentFilter(const QString &filter, const InfoHashSet &hashSet, const QString &category, const QString &tag)
|
||||
TorrentFilter::TorrentFilter(const QString &filter, const TorrentIDSet &idSet, const QString &category, const QString &tag)
|
||||
: m_type(All)
|
||||
, m_category(category)
|
||||
, m_tag(tag)
|
||||
, m_hashSet(hashSet)
|
||||
, m_idSet(idSet)
|
||||
{
|
||||
setTypeByName(filter);
|
||||
}
|
||||
@ -107,11 +107,11 @@ bool TorrentFilter::setTypeByName(const QString &filter)
|
||||
return setType(type);
|
||||
}
|
||||
|
||||
bool TorrentFilter::setHashSet(const InfoHashSet &hashSet)
|
||||
bool TorrentFilter::setTorrentIDSet(const TorrentIDSet &idSet)
|
||||
{
|
||||
if (m_hashSet != hashSet)
|
||||
if (m_idSet != idSet)
|
||||
{
|
||||
m_hashSet = hashSet;
|
||||
m_idSet = idSet;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -189,9 +189,9 @@ bool TorrentFilter::matchState(const BitTorrent::Torrent *const torrent) const
|
||||
|
||||
bool TorrentFilter::matchHash(const BitTorrent::Torrent *const torrent) const
|
||||
{
|
||||
if (m_hashSet == AnyHash) return true;
|
||||
if (m_idSet == AnyID) return true;
|
||||
|
||||
return m_hashSet.contains(torrent->hash());
|
||||
return m_idSet.contains(torrent->id());
|
||||
}
|
||||
|
||||
bool TorrentFilter::matchCategory(const BitTorrent::Torrent *const torrent) const
|
||||
|
@ -38,7 +38,7 @@ namespace BitTorrent
|
||||
class Torrent;
|
||||
}
|
||||
|
||||
using InfoHashSet = QSet<BitTorrent::InfoHash>;
|
||||
using TorrentIDSet = QSet<BitTorrent::TorrentID>;
|
||||
|
||||
class TorrentFilter
|
||||
{
|
||||
@ -61,7 +61,7 @@ public:
|
||||
|
||||
// These mean any permutation, including no category / tag.
|
||||
static const QString AnyCategory;
|
||||
static const InfoHashSet AnyHash;
|
||||
static const TorrentIDSet AnyID;
|
||||
static const QString AnyTag;
|
||||
|
||||
static const TorrentFilter DownloadingTorrent;
|
||||
@ -79,12 +79,12 @@ public:
|
||||
TorrentFilter() = default;
|
||||
// category & tags: pass empty string for uncategorized / untagged torrents.
|
||||
// Pass null string (QString()) to disable filtering (i.e. all torrents).
|
||||
TorrentFilter(Type type, const InfoHashSet &hashSet = AnyHash, const QString &category = AnyCategory, const QString &tag = AnyTag);
|
||||
TorrentFilter(const QString &filter, const InfoHashSet &hashSet = AnyHash, const QString &category = AnyCategory, const QString &tags = AnyTag);
|
||||
TorrentFilter(Type type, const TorrentIDSet &idSet = AnyID, const QString &category = AnyCategory, const QString &tag = AnyTag);
|
||||
TorrentFilter(const QString &filter, const TorrentIDSet &idSet = AnyID, const QString &category = AnyCategory, const QString &tags = AnyTag);
|
||||
|
||||
bool setType(Type type);
|
||||
bool setTypeByName(const QString &filter);
|
||||
bool setHashSet(const InfoHashSet &hashSet);
|
||||
bool setTorrentIDSet(const TorrentIDSet &idSet);
|
||||
bool setCategory(const QString &category);
|
||||
bool setTag(const QString &tag);
|
||||
|
||||
@ -99,5 +99,5 @@ private:
|
||||
Type m_type {All};
|
||||
QString m_category;
|
||||
QString m_tag;
|
||||
InfoHashSet m_hashSet;
|
||||
TorrentIDSet m_idSet;
|
||||
};
|
||||
|
@ -270,12 +270,12 @@ bool AddNewTorrentDialog::loadTorrentFile(const QString &torrentPath)
|
||||
bool AddNewTorrentDialog::loadTorrentImpl()
|
||||
{
|
||||
m_hasMetadata = true;
|
||||
const BitTorrent::InfoHash infoHash = m_torrentInfo.hash();
|
||||
const auto torrentID = BitTorrent::TorrentID::fromInfoHash(m_torrentInfo.infoHash());
|
||||
|
||||
// Prevent showing the dialog if download is already present
|
||||
if (BitTorrent::Session::instance()->isKnownTorrent(infoHash))
|
||||
if (BitTorrent::Session::instance()->isKnownTorrent(torrentID))
|
||||
{
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(infoHash);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(torrentID);
|
||||
if (torrent)
|
||||
{
|
||||
if (torrent->isPrivate() || m_torrentInfo.isPrivate())
|
||||
@ -296,7 +296,7 @@ bool AddNewTorrentDialog::loadTorrentImpl()
|
||||
return false;
|
||||
}
|
||||
|
||||
m_ui->labelHashData->setText(infoHash.toString());
|
||||
m_ui->labelHashData->setText(torrentID.toString());
|
||||
setupTreeview();
|
||||
TMMChanged(m_ui->comboTTM->currentIndex());
|
||||
return true;
|
||||
@ -312,11 +312,11 @@ bool AddNewTorrentDialog::loadMagnet(const BitTorrent::MagnetUri &magnetUri)
|
||||
|
||||
m_torrentGuard = std::make_unique<TorrentFileGuard>();
|
||||
|
||||
const BitTorrent::InfoHash infoHash = magnetUri.hash();
|
||||
const auto torrentID = BitTorrent::TorrentID::fromInfoHash(magnetUri.infoHash());
|
||||
// Prevent showing the dialog if download is already present
|
||||
if (BitTorrent::Session::instance()->isKnownTorrent(infoHash))
|
||||
if (BitTorrent::Session::instance()->isKnownTorrent(torrentID))
|
||||
{
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(infoHash);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(torrentID);
|
||||
if (torrent)
|
||||
{
|
||||
if (torrent->isPrivate())
|
||||
@ -348,7 +348,7 @@ bool AddNewTorrentDialog::loadMagnet(const BitTorrent::MagnetUri &magnetUri)
|
||||
|
||||
BitTorrent::Session::instance()->downloadMetadata(magnetUri);
|
||||
setMetadataProgressIndicator(true, tr("Retrieving metadata..."));
|
||||
m_ui->labelHashData->setText(infoHash.toString());
|
||||
m_ui->labelHashData->setText(torrentID.toString());
|
||||
|
||||
m_magnetURI = magnetUri;
|
||||
return true;
|
||||
@ -629,7 +629,7 @@ void AddNewTorrentDialog::reject()
|
||||
if (!m_hasMetadata)
|
||||
{
|
||||
setMetadataProgressIndicator(false);
|
||||
BitTorrent::Session::instance()->cancelDownloadMetadata(m_magnetURI.hash());
|
||||
BitTorrent::Session::instance()->cancelDownloadMetadata(m_magnetURI.infoHash().toTorrentID());
|
||||
}
|
||||
|
||||
QDialog::reject();
|
||||
@ -637,7 +637,7 @@ void AddNewTorrentDialog::reject()
|
||||
|
||||
void AddNewTorrentDialog::updateMetadata(const BitTorrent::TorrentInfo &metadata)
|
||||
{
|
||||
if (metadata.hash() != m_magnetURI.hash()) return;
|
||||
if (metadata.infoHash() != m_magnetURI.infoHash()) return;
|
||||
|
||||
disconnect(BitTorrent::Session::instance(), &BitTorrent::Session::metadataDownloaded, this, &AddNewTorrentDialog::updateMetadata);
|
||||
|
||||
|
@ -958,7 +958,7 @@ void MainWindow::askRecursiveTorrentDownloadConfirmation(BitTorrent::Torrent *co
|
||||
Preferences *const pref = Preferences::instance();
|
||||
if (pref->recursiveDownloadDisabled()) return;
|
||||
|
||||
const auto torrentHash = torrent->hash();
|
||||
const auto torrentID = torrent->id();
|
||||
|
||||
QMessageBox *confirmBox = new QMessageBox(QMessageBox::Question, tr("Recursive download confirmation")
|
||||
, tr("The torrent '%1' contains torrent files, do you want to proceed with their download?").arg(torrent->name())
|
||||
@ -969,10 +969,10 @@ void MainWindow::askRecursiveTorrentDownloadConfirmation(BitTorrent::Torrent *co
|
||||
const QPushButton *yes = confirmBox->addButton(tr("Yes"), QMessageBox::YesRole);
|
||||
/*QPushButton *no = */ confirmBox->addButton(tr("No"), QMessageBox::NoRole);
|
||||
const QPushButton *never = confirmBox->addButton(tr("Never"), QMessageBox::NoRole);
|
||||
connect(confirmBox, &QMessageBox::buttonClicked, this, [torrentHash, yes, never](const QAbstractButton *button)
|
||||
connect(confirmBox, &QMessageBox::buttonClicked, this, [torrentID, yes, never](const QAbstractButton *button)
|
||||
{
|
||||
if (button == yes)
|
||||
BitTorrent::Session::instance()->recursiveTorrentDownload(torrentHash);
|
||||
BitTorrent::Session::instance()->recursiveTorrentDownload(torrentID);
|
||||
if (button == never)
|
||||
Preferences::instance()->disableRecursiveDownload();
|
||||
});
|
||||
|
@ -312,8 +312,9 @@ void PropertiesWidget::loadTorrentInfos(BitTorrent::Torrent *const torrent)
|
||||
|
||||
// Save path
|
||||
updateSavePath(m_torrent);
|
||||
// Hash
|
||||
m_ui->labelHashVal->setText(m_torrent->hash().toString());
|
||||
// Info hash (Truncated info hash (torrent ID) with libtorrent2)
|
||||
// TODO: Update label for this property to express its meaning more clearly (or change it to display real info hash(es))
|
||||
m_ui->labelHashVal->setText(m_torrent->id().toString());
|
||||
m_propListModel->model()->clear();
|
||||
if (m_torrent->hasMetadata())
|
||||
{
|
||||
|
@ -77,10 +77,10 @@ TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QVector<BitTor
|
||||
const bool isFirstTorrentPEXDisabled = torrents[0]->isPEXDisabled();
|
||||
const bool isFirstTorrentLSDDisabled = torrents[0]->isLSDDisabled();
|
||||
|
||||
m_torrentHashes.reserve(torrents.size());
|
||||
m_torrentIDs.reserve(torrents.size());
|
||||
for (const BitTorrent::Torrent *torrent : torrents)
|
||||
{
|
||||
m_torrentHashes << torrent->hash();
|
||||
m_torrentIDs << torrent->id();
|
||||
if (allSameUpLimit)
|
||||
{
|
||||
if (qMax(0, torrent->uploadLimit()) != firstTorrentUpLimit)
|
||||
@ -288,9 +288,9 @@ void TorrentOptionsDialog::accept()
|
||||
}
|
||||
|
||||
const auto *session = BitTorrent::Session::instance();
|
||||
for (const BitTorrent::InfoHash &hash : asConst(m_torrentHashes))
|
||||
for (const BitTorrent::TorrentID &id : asConst(m_torrentIDs))
|
||||
{
|
||||
BitTorrent::Torrent *torrent = session->findTorrent(hash);
|
||||
BitTorrent::Torrent *torrent = session->findTorrent(id);
|
||||
if (!torrent) continue;
|
||||
|
||||
if (m_initialValues.upSpeedLimit != m_ui->spinUploadLimit->value())
|
||||
|
@ -36,8 +36,8 @@
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class InfoHash;
|
||||
class Torrent;
|
||||
class TorrentID;
|
||||
}
|
||||
|
||||
namespace Ui
|
||||
@ -67,7 +67,7 @@ private:
|
||||
qreal getRatio() const;
|
||||
int getSeedingTime() const;
|
||||
|
||||
QVector<BitTorrent::InfoHash> m_torrentHashes;
|
||||
QVector<BitTorrent::TorrentID> m_torrentIDs;
|
||||
Ui::TorrentOptionsDialog *m_ui;
|
||||
SettingValue<QSize> m_storeDialogSize;
|
||||
struct
|
||||
|
@ -321,7 +321,7 @@ TrackerFiltersList::~TrackerFiltersList()
|
||||
Utils::Fs::forceRemove(iconPath);
|
||||
}
|
||||
|
||||
void TrackerFiltersList::addItem(const QString &tracker, const BitTorrent::InfoHash &hash)
|
||||
void TrackerFiltersList::addItem(const QString &tracker, const BitTorrent::TorrentID &id)
|
||||
{
|
||||
const QString host {getHost(tracker)};
|
||||
const bool exists {m_trackers.contains(host)};
|
||||
@ -329,7 +329,7 @@ void TrackerFiltersList::addItem(const QString &tracker, const BitTorrent::InfoH
|
||||
|
||||
if (exists)
|
||||
{
|
||||
if (m_trackers.value(host).contains(hash))
|
||||
if (m_trackers.value(host).contains(id))
|
||||
return;
|
||||
|
||||
trackerItem = item((host == NULL_HOST)
|
||||
@ -346,18 +346,18 @@ void TrackerFiltersList::addItem(const QString &tracker, const BitTorrent::InfoH
|
||||
}
|
||||
if (!trackerItem) return;
|
||||
|
||||
QSet<BitTorrent::InfoHash> &hashes {m_trackers[host]};
|
||||
hashes.insert(hash);
|
||||
QSet<BitTorrent::TorrentID> &torrentIDs {m_trackers[host]};
|
||||
torrentIDs.insert(id);
|
||||
|
||||
if (host == NULL_HOST)
|
||||
{
|
||||
trackerItem->setText(tr("Trackerless (%1)").arg(hashes.size()));
|
||||
trackerItem->setText(tr("Trackerless (%1)").arg(torrentIDs.size()));
|
||||
if (currentRow() == TRACKERLESS_ROW)
|
||||
applyFilter(TRACKERLESS_ROW);
|
||||
return;
|
||||
}
|
||||
|
||||
trackerItem->setText(QString::fromLatin1("%1 (%2)").arg(host, QString::number(hashes.size())));
|
||||
trackerItem->setText(QString::fromLatin1("%1 (%2)").arg(host, QString::number(torrentIDs.size())));
|
||||
if (exists)
|
||||
{
|
||||
if (currentRow() == rowFromTracker(host))
|
||||
@ -379,14 +379,14 @@ void TrackerFiltersList::addItem(const QString &tracker, const BitTorrent::InfoH
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void TrackerFiltersList::removeItem(const QString &tracker, const BitTorrent::InfoHash &hash)
|
||||
void TrackerFiltersList::removeItem(const QString &tracker, const BitTorrent::TorrentID &id)
|
||||
{
|
||||
const QString host = getHost(tracker);
|
||||
QSet<BitTorrent::InfoHash> hashes = m_trackers.value(host);
|
||||
QSet<BitTorrent::TorrentID> torrentIDs = m_trackers.value(host);
|
||||
|
||||
if (hashes.empty())
|
||||
if (torrentIDs.empty())
|
||||
return;
|
||||
hashes.remove(hash);
|
||||
torrentIDs.remove(id);
|
||||
|
||||
int row = 0;
|
||||
QListWidgetItem *trackerItem = nullptr;
|
||||
@ -394,11 +394,11 @@ void TrackerFiltersList::removeItem(const QString &tracker, const BitTorrent::In
|
||||
if (!host.isEmpty())
|
||||
{
|
||||
// Remove from 'Error' and 'Warning' view
|
||||
trackerSuccess(hash, tracker);
|
||||
trackerSuccess(id, tracker);
|
||||
row = rowFromTracker(host);
|
||||
trackerItem = item(row);
|
||||
|
||||
if (hashes.empty())
|
||||
if (torrentIDs.empty())
|
||||
{
|
||||
if (currentRow() == row)
|
||||
setCurrentRow(0, QItemSelectionModel::SelectCurrent);
|
||||
@ -409,27 +409,27 @@ void TrackerFiltersList::removeItem(const QString &tracker, const BitTorrent::In
|
||||
}
|
||||
|
||||
if (trackerItem)
|
||||
trackerItem->setText(QString::fromLatin1("%1 (%2)").arg(host, QString::number(hashes.size())));
|
||||
trackerItem->setText(QString::fromLatin1("%1 (%2)").arg(host, QString::number(torrentIDs.size())));
|
||||
}
|
||||
else
|
||||
{
|
||||
row = 1;
|
||||
trackerItem = item(TRACKERLESS_ROW);
|
||||
trackerItem->setText(tr("Trackerless (%1)").arg(hashes.size()));
|
||||
trackerItem->setText(tr("Trackerless (%1)").arg(torrentIDs.size()));
|
||||
}
|
||||
|
||||
m_trackers.insert(host, hashes);
|
||||
m_trackers.insert(host, torrentIDs);
|
||||
|
||||
if (currentRow() == row)
|
||||
applyFilter(row);
|
||||
}
|
||||
|
||||
void TrackerFiltersList::changeTrackerless(const bool trackerless, const BitTorrent::InfoHash &hash)
|
||||
void TrackerFiltersList::changeTrackerless(const bool trackerless, const BitTorrent::TorrentID &id)
|
||||
{
|
||||
if (trackerless)
|
||||
addItem(NULL_HOST, hash);
|
||||
addItem(NULL_HOST, id);
|
||||
else
|
||||
removeItem(NULL_HOST, hash);
|
||||
removeItem(NULL_HOST, id);
|
||||
}
|
||||
|
||||
void TrackerFiltersList::setDownloadTrackerFavicon(bool value)
|
||||
@ -452,9 +452,9 @@ void TrackerFiltersList::setDownloadTrackerFavicon(bool value)
|
||||
}
|
||||
}
|
||||
|
||||
void TrackerFiltersList::trackerSuccess(const BitTorrent::InfoHash &hash, const QString &tracker)
|
||||
void TrackerFiltersList::trackerSuccess(const BitTorrent::TorrentID &id, const QString &tracker)
|
||||
{
|
||||
const auto errorHashesIter = m_errors.find(hash);
|
||||
const auto errorHashesIter = m_errors.find(id);
|
||||
if (errorHashesIter != m_errors.end())
|
||||
{
|
||||
QSet<QString> &errored = *errorHashesIter;
|
||||
@ -468,7 +468,7 @@ void TrackerFiltersList::trackerSuccess(const BitTorrent::InfoHash &hash, const
|
||||
}
|
||||
}
|
||||
|
||||
const auto warningHashesIter = m_warnings.find(hash);
|
||||
const auto warningHashesIter = m_warnings.find(id);
|
||||
if (warningHashesIter != m_warnings.end())
|
||||
{
|
||||
QSet<QString> &warned = *warningHashesIter;
|
||||
@ -483,9 +483,9 @@ void TrackerFiltersList::trackerSuccess(const BitTorrent::InfoHash &hash, const
|
||||
}
|
||||
}
|
||||
|
||||
void TrackerFiltersList::trackerError(const BitTorrent::InfoHash &hash, const QString &tracker)
|
||||
void TrackerFiltersList::trackerError(const BitTorrent::TorrentID &id, const QString &tracker)
|
||||
{
|
||||
QSet<QString> &trackers {m_errors[hash]};
|
||||
QSet<QString> &trackers {m_errors[id]};
|
||||
if (trackers.contains(tracker))
|
||||
return;
|
||||
|
||||
@ -495,9 +495,9 @@ void TrackerFiltersList::trackerError(const BitTorrent::InfoHash &hash, const QS
|
||||
applyFilter(ERROR_ROW);
|
||||
}
|
||||
|
||||
void TrackerFiltersList::trackerWarning(const BitTorrent::InfoHash &hash, const QString &tracker)
|
||||
void TrackerFiltersList::trackerWarning(const BitTorrent::TorrentID &id, const QString &tracker)
|
||||
{
|
||||
QSet<QString> &trackers {m_warnings[hash]};
|
||||
QSet<QString> &trackers {m_warnings[id]};
|
||||
if (trackers.contains(tracker))
|
||||
return;
|
||||
|
||||
@ -572,33 +572,33 @@ void TrackerFiltersList::applyFilter(const int row)
|
||||
if (row == ALL_ROW)
|
||||
transferList->applyTrackerFilterAll();
|
||||
else if (isVisible())
|
||||
transferList->applyTrackerFilter(getInfoHashes(row));
|
||||
transferList->applyTrackerFilter(getTorrentIDs(row));
|
||||
}
|
||||
|
||||
void TrackerFiltersList::handleNewTorrent(BitTorrent::Torrent *const torrent)
|
||||
{
|
||||
const BitTorrent::InfoHash hash {torrent->hash()};
|
||||
const BitTorrent::TorrentID torrentID {torrent->id()};
|
||||
const QVector<BitTorrent::TrackerEntry> trackers {torrent->trackers()};
|
||||
for (const BitTorrent::TrackerEntry &tracker : trackers)
|
||||
addItem(tracker.url, hash);
|
||||
addItem(tracker.url, torrentID);
|
||||
|
||||
// Check for trackerless torrent
|
||||
if (trackers.isEmpty())
|
||||
addItem(NULL_HOST, hash);
|
||||
addItem(NULL_HOST, torrentID);
|
||||
|
||||
item(ALL_ROW)->setText(tr("All (%1)", "this is for the tracker filter").arg(++m_totalTorrents));
|
||||
}
|
||||
|
||||
void TrackerFiltersList::torrentAboutToBeDeleted(BitTorrent::Torrent *const torrent)
|
||||
{
|
||||
const BitTorrent::InfoHash hash {torrent->hash()};
|
||||
const BitTorrent::TorrentID torrentID {torrent->id()};
|
||||
const QVector<BitTorrent::TrackerEntry> trackers {torrent->trackers()};
|
||||
for (const BitTorrent::TrackerEntry &tracker : trackers)
|
||||
removeItem(tracker.url, hash);
|
||||
removeItem(tracker.url, torrentID);
|
||||
|
||||
// Check for trackerless torrent
|
||||
if (trackers.isEmpty())
|
||||
removeItem(NULL_HOST, hash);
|
||||
removeItem(NULL_HOST, torrentID);
|
||||
|
||||
item(ALL_ROW)->setText(tr("All (%1)", "this is for the tracker filter").arg(--m_totalTorrents));
|
||||
}
|
||||
@ -624,7 +624,7 @@ int TrackerFiltersList::rowFromTracker(const QString &tracker) const
|
||||
return -1;
|
||||
}
|
||||
|
||||
QSet<BitTorrent::InfoHash> TrackerFiltersList::getInfoHashes(const int row) const
|
||||
QSet<BitTorrent::TorrentID> TrackerFiltersList::getTorrentIDs(const int row) const
|
||||
{
|
||||
switch (row)
|
||||
{
|
||||
@ -727,11 +727,11 @@ TransferListFiltersWidget::TransferListFiltersWidget(QWidget *parent, TransferLi
|
||||
connect(trackerLabel, &QCheckBox::toggled, m_trackerFilters, &TrackerFiltersList::toggleFilter);
|
||||
connect(trackerLabel, &QCheckBox::toggled, pref, &Preferences::setTrackerFilterState);
|
||||
|
||||
connect(this, qOverload<const BitTorrent::InfoHash &, const QString &>(&TransferListFiltersWidget::trackerSuccess)
|
||||
connect(this, qOverload<const BitTorrent::TorrentID &, const QString &>(&TransferListFiltersWidget::trackerSuccess)
|
||||
, m_trackerFilters, &TrackerFiltersList::trackerSuccess);
|
||||
connect(this, qOverload<const BitTorrent::InfoHash &, const QString &>(&TransferListFiltersWidget::trackerError)
|
||||
connect(this, qOverload<const BitTorrent::TorrentID &, const QString &>(&TransferListFiltersWidget::trackerError)
|
||||
, m_trackerFilters, &TrackerFiltersList::trackerError);
|
||||
connect(this, qOverload<const BitTorrent::InfoHash &, const QString &>(&TransferListFiltersWidget::trackerWarning)
|
||||
connect(this, qOverload<const BitTorrent::TorrentID &, const QString &>(&TransferListFiltersWidget::trackerWarning)
|
||||
, m_trackerFilters, &TrackerFiltersList::trackerWarning);
|
||||
}
|
||||
|
||||
@ -743,33 +743,33 @@ void TransferListFiltersWidget::setDownloadTrackerFavicon(bool value)
|
||||
void TransferListFiltersWidget::addTrackers(const BitTorrent::Torrent *torrent, const QVector<BitTorrent::TrackerEntry> &trackers)
|
||||
{
|
||||
for (const BitTorrent::TrackerEntry &tracker : trackers)
|
||||
m_trackerFilters->addItem(tracker.url, torrent->hash());
|
||||
m_trackerFilters->addItem(tracker.url, torrent->id());
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::removeTrackers(const BitTorrent::Torrent *torrent, const QVector<BitTorrent::TrackerEntry> &trackers)
|
||||
{
|
||||
for (const BitTorrent::TrackerEntry &tracker : trackers)
|
||||
m_trackerFilters->removeItem(tracker.url, torrent->hash());
|
||||
m_trackerFilters->removeItem(tracker.url, torrent->id());
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::changeTrackerless(const BitTorrent::Torrent *torrent, const bool trackerless)
|
||||
{
|
||||
m_trackerFilters->changeTrackerless(trackerless, torrent->hash());
|
||||
m_trackerFilters->changeTrackerless(trackerless, torrent->id());
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::trackerSuccess(const BitTorrent::Torrent *torrent, const QString &tracker)
|
||||
{
|
||||
emit trackerSuccess(torrent->hash(), tracker);
|
||||
emit trackerSuccess(torrent->id(), tracker);
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::trackerWarning(const BitTorrent::Torrent *torrent, const QString &tracker)
|
||||
{
|
||||
emit trackerWarning(torrent->hash(), tracker);
|
||||
emit trackerWarning(torrent->id(), tracker);
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::trackerError(const BitTorrent::Torrent *torrent, const QString &tracker)
|
||||
{
|
||||
emit trackerError(torrent->hash(), tracker);
|
||||
emit trackerError(torrent->id(), tracker);
|
||||
}
|
||||
|
||||
void TransferListFiltersWidget::onCategoryFilterStateChanged(bool enabled)
|
||||
|
@ -39,8 +39,8 @@ class TransferListWidget;
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class InfoHash;
|
||||
class Torrent;
|
||||
class TorrentID;
|
||||
struct TrackerEntry;
|
||||
}
|
||||
|
||||
@ -104,15 +104,15 @@ public:
|
||||
~TrackerFiltersList() override;
|
||||
|
||||
// Redefine addItem() to make sure the list stays sorted
|
||||
void addItem(const QString &tracker, const BitTorrent::InfoHash &hash);
|
||||
void removeItem(const QString &tracker, const BitTorrent::InfoHash &hash);
|
||||
void changeTrackerless(bool trackerless, const BitTorrent::InfoHash &hash);
|
||||
void addItem(const QString &tracker, const BitTorrent::TorrentID &id);
|
||||
void removeItem(const QString &tracker, const BitTorrent::TorrentID &id);
|
||||
void changeTrackerless(bool trackerless, const BitTorrent::TorrentID &id);
|
||||
void setDownloadTrackerFavicon(bool value);
|
||||
|
||||
public slots:
|
||||
void trackerSuccess(const BitTorrent::InfoHash &hash, const QString &tracker);
|
||||
void trackerError(const BitTorrent::InfoHash &hash, const QString &tracker);
|
||||
void trackerWarning(const BitTorrent::InfoHash &hash, const QString &tracker);
|
||||
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:
|
||||
void handleFavicoDownloadFinished(const Net::DownloadResult &result);
|
||||
@ -126,12 +126,12 @@ private:
|
||||
void torrentAboutToBeDeleted(BitTorrent::Torrent *const torrent) override;
|
||||
QString trackerFromRow(int row) const;
|
||||
int rowFromTracker(const QString &tracker) const;
|
||||
QSet<BitTorrent::InfoHash> getInfoHashes(int row) const;
|
||||
QSet<BitTorrent::TorrentID> getTorrentIDs(int row) const;
|
||||
void downloadFavicon(const QString &url);
|
||||
|
||||
QHash<QString, QSet<BitTorrent::InfoHash>> m_trackers; // <tracker host, torrent hashes>
|
||||
QHash<BitTorrent::InfoHash, QSet<QString>> m_errors; // <torrent hash, tracker hosts>
|
||||
QHash<BitTorrent::InfoHash, QSet<QString>> m_warnings; // <torrent hash, tracker hosts>
|
||||
QHash<QString, QSet<BitTorrent::TorrentID>> m_trackers; // <tracker host, torrent IDs>
|
||||
QHash<BitTorrent::TorrentID, QSet<QString>> m_errors; // <torrent ID, tracker hosts>
|
||||
QHash<BitTorrent::TorrentID, QSet<QString>> m_warnings; // <torrent ID, tracker hosts>
|
||||
QStringList m_iconPaths;
|
||||
int m_totalTorrents;
|
||||
bool m_downloadTrackerFavicon;
|
||||
@ -158,9 +158,9 @@ public slots:
|
||||
void trackerError(const BitTorrent::Torrent *torrent, const QString &tracker);
|
||||
|
||||
signals:
|
||||
void trackerSuccess(const BitTorrent::InfoHash &hash, const QString &tracker);
|
||||
void trackerError(const BitTorrent::InfoHash &hash, const QString &tracker);
|
||||
void trackerWarning(const BitTorrent::InfoHash &hash, const QString &tracker);
|
||||
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:
|
||||
void onCategoryFilterStateChanged(bool enabled);
|
||||
|
@ -99,15 +99,15 @@ void TransferListSortModel::disableTagFilter()
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void TransferListSortModel::setTrackerFilter(const QSet<BitTorrent::InfoHash> &hashes)
|
||||
void TransferListSortModel::setTrackerFilter(const QSet<BitTorrent::TorrentID> &torrentIDs)
|
||||
{
|
||||
if (m_filter.setHashSet(hashes))
|
||||
if (m_filter.setTorrentIDSet(torrentIDs))
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void TransferListSortModel::disableTrackerFilter()
|
||||
{
|
||||
if (m_filter.setHashSet(TorrentFilter::AnyHash))
|
||||
if (m_filter.setTorrentIDSet(TorrentFilter::AnyID))
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
void disableCategoryFilter();
|
||||
void setTagFilter(const QString &tag);
|
||||
void disableTagFilter();
|
||||
void setTrackerFilter(const QSet<BitTorrent::InfoHash> &hashes);
|
||||
void setTrackerFilter(const QSet<BitTorrent::TorrentID> &torrentIDs);
|
||||
void disableTrackerFilter();
|
||||
|
||||
private:
|
||||
|
@ -78,13 +78,13 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
QVector<BitTorrent::InfoHash> extractHashes(const QVector<BitTorrent::Torrent *> &torrents)
|
||||
QVector<BitTorrent::TorrentID> extractIDs(const QVector<BitTorrent::Torrent *> &torrents)
|
||||
{
|
||||
QVector<BitTorrent::InfoHash> hashes;
|
||||
hashes.reserve(torrents.size());
|
||||
QVector<BitTorrent::TorrentID> torrentIDs;
|
||||
torrentIDs.reserve(torrents.size());
|
||||
for (const BitTorrent::Torrent *torrent : torrents)
|
||||
hashes << torrent->hash();
|
||||
return hashes;
|
||||
torrentIDs << torrent->id();
|
||||
return torrentIDs;
|
||||
}
|
||||
|
||||
bool torrentContainsPreviewableFiles(const BitTorrent::Torrent *const torrent)
|
||||
@ -121,7 +121,7 @@ namespace
|
||||
auto *session = BitTorrent::Session::instance();
|
||||
const DeleteOption deleteOption = isDeleteFileSelected ? DeleteTorrentAndFiles : DeleteTorrent;
|
||||
for (const BitTorrent::Torrent *torrent : torrents)
|
||||
session->deleteTorrent(torrent->hash(), deleteOption);
|
||||
session->deleteTorrent(torrent->id(), deleteOption);
|
||||
}
|
||||
}
|
||||
|
||||
@ -452,26 +452,26 @@ void TransferListWidget::increaseQueuePosSelectedTorrents()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if (m_mainWindow->currentTabWidget() == this)
|
||||
BitTorrent::Session::instance()->increaseTorrentsQueuePos(extractHashes(getSelectedTorrents()));
|
||||
BitTorrent::Session::instance()->increaseTorrentsQueuePos(extractIDs(getSelectedTorrents()));
|
||||
}
|
||||
|
||||
void TransferListWidget::decreaseQueuePosSelectedTorrents()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if (m_mainWindow->currentTabWidget() == this)
|
||||
BitTorrent::Session::instance()->decreaseTorrentsQueuePos(extractHashes(getSelectedTorrents()));
|
||||
BitTorrent::Session::instance()->decreaseTorrentsQueuePos(extractIDs(getSelectedTorrents()));
|
||||
}
|
||||
|
||||
void TransferListWidget::topQueuePosSelectedTorrents()
|
||||
{
|
||||
if (m_mainWindow->currentTabWidget() == this)
|
||||
BitTorrent::Session::instance()->topTorrentsQueuePos(extractHashes(getSelectedTorrents()));
|
||||
BitTorrent::Session::instance()->topTorrentsQueuePos(extractIDs(getSelectedTorrents()));
|
||||
}
|
||||
|
||||
void TransferListWidget::bottomQueuePosSelectedTorrents()
|
||||
{
|
||||
if (m_mainWindow->currentTabWidget() == this)
|
||||
BitTorrent::Session::instance()->bottomTorrentsQueuePos(extractHashes(getSelectedTorrents()));
|
||||
BitTorrent::Session::instance()->bottomTorrentsQueuePos(extractIDs(getSelectedTorrents()));
|
||||
}
|
||||
|
||||
void TransferListWidget::copySelectedMagnetURIs() const
|
||||
@ -494,11 +494,11 @@ void TransferListWidget::copySelectedNames() const
|
||||
|
||||
void TransferListWidget::copySelectedHashes() const
|
||||
{
|
||||
QStringList torrentHashes;
|
||||
QStringList torrentIDs;
|
||||
for (BitTorrent::Torrent *const torrent : asConst(getSelectedTorrents()))
|
||||
torrentHashes << torrent->hash().toString();
|
||||
torrentIDs << torrent->id().toString();
|
||||
|
||||
qApp->clipboard()->setText(torrentHashes.join('\n'));
|
||||
qApp->clipboard()->setText(torrentIDs.join('\n'));
|
||||
}
|
||||
|
||||
void TransferListWidget::hideQueuePosColumn(bool hide)
|
||||
@ -1129,9 +1129,9 @@ void TransferListWidget::applyTrackerFilterAll()
|
||||
m_sortFilterModel->disableTrackerFilter();
|
||||
}
|
||||
|
||||
void TransferListWidget::applyTrackerFilter(const QSet<BitTorrent::InfoHash> &hashes)
|
||||
void TransferListWidget::applyTrackerFilter(const QSet<BitTorrent::TorrentID> &torrentIDs)
|
||||
{
|
||||
m_sortFilterModel->setTrackerFilter(hashes);
|
||||
m_sortFilterModel->setTrackerFilter(torrentIDs);
|
||||
}
|
||||
|
||||
void TransferListWidget::applyNameFilter(const QString &name)
|
||||
|
@ -39,8 +39,8 @@ class TransferListSortModel;
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
class InfoHash;
|
||||
class Torrent;
|
||||
class TorrentID;
|
||||
}
|
||||
|
||||
class TransferListWidget final : public QTreeView
|
||||
@ -88,7 +88,7 @@ public slots:
|
||||
void applyCategoryFilter(const QString &category);
|
||||
void applyTagFilter(const QString &tag);
|
||||
void applyTrackerFilterAll();
|
||||
void applyTrackerFilter(const QSet<BitTorrent::InfoHash> &hashes);
|
||||
void applyTrackerFilter(const QSet<BitTorrent::TorrentID> &torrentIDs);
|
||||
void previewFile(const QString &filePath);
|
||||
void renameSelectedTorrent();
|
||||
|
||||
|
@ -103,7 +103,8 @@ QVariantMap serialize(const BitTorrent::Torrent &torrent)
|
||||
};
|
||||
|
||||
return {
|
||||
{KEY_TORRENT_HASH, QString(torrent.hash().toString())},
|
||||
// TODO: Add fields for real SHA1 and SHA256 hashes
|
||||
{KEY_TORRENT_ID, QString(torrent.id().toString())},
|
||||
{KEY_TORRENT_NAME, torrent.name()},
|
||||
{KEY_TORRENT_MAGNET_URI, torrent.createMagnetURI()},
|
||||
{KEY_TORRENT_SIZE, torrent.wantedSize()},
|
||||
|
@ -36,7 +36,7 @@ namespace BitTorrent
|
||||
}
|
||||
|
||||
// Torrent keys
|
||||
const char KEY_TORRENT_HASH[] = "hash";
|
||||
const char KEY_TORRENT_ID[] = "hash";
|
||||
const char KEY_TORRENT_NAME[] = "name";
|
||||
const char KEY_TORRENT_MAGNET_URI[] = "magnet_uri";
|
||||
const char KEY_TORRENT_SIZE[] = "size";
|
||||
|
@ -460,10 +460,10 @@ void SyncController::maindataAction()
|
||||
QHash<QString, QStringList> trackers;
|
||||
for (const BitTorrent::Torrent *torrent : asConst(session->torrents()))
|
||||
{
|
||||
const BitTorrent::InfoHash torrentHash = torrent->hash();
|
||||
const BitTorrent::TorrentID torrentID = torrent->id();
|
||||
|
||||
QVariantMap map = serialize(*torrent);
|
||||
map.remove(KEY_TORRENT_HASH);
|
||||
map.remove(KEY_TORRENT_ID);
|
||||
|
||||
// Calculated last activity time can differ from actual value by up to 10 seconds (this is a libtorrent issue).
|
||||
// So we don't need unnecessary updates of last activity time in response.
|
||||
@ -471,11 +471,11 @@ void SyncController::maindataAction()
|
||||
if (iterTorrents != lastResponse.end())
|
||||
{
|
||||
const QVariantHash lastResponseTorrents = iterTorrents->toHash();
|
||||
const auto iterHash = lastResponseTorrents.find(torrentHash.toString());
|
||||
const auto iterID = lastResponseTorrents.find(torrentID.toString());
|
||||
|
||||
if (iterHash != lastResponseTorrents.end())
|
||||
if (iterID != lastResponseTorrents.end())
|
||||
{
|
||||
const QVariantMap torrentData = iterHash->toMap();
|
||||
const QVariantMap torrentData = iterID->toMap();
|
||||
const auto iterLastActivity = torrentData.find(KEY_TORRENT_LAST_ACTIVITY_TIME);
|
||||
|
||||
if (iterLastActivity != torrentData.end())
|
||||
@ -488,9 +488,9 @@ void SyncController::maindataAction()
|
||||
}
|
||||
|
||||
for (const BitTorrent::TrackerEntry &tracker : asConst(torrent->trackers()))
|
||||
trackers[tracker.url] << torrentHash.toString();
|
||||
trackers[tracker.url] << torrentID.toString();
|
||||
|
||||
torrents[torrentHash.toString()] = map;
|
||||
torrents[torrentID.toString()] = map;
|
||||
}
|
||||
data["torrents"] = torrents;
|
||||
|
||||
@ -534,15 +534,15 @@ void SyncController::maindataAction()
|
||||
}
|
||||
|
||||
// GET param:
|
||||
// - hash (string): torrent hash
|
||||
// - hash (string): torrent hash (ID)
|
||||
// - rid (int): last response id
|
||||
void SyncController::torrentPeersAction()
|
||||
{
|
||||
auto lastResponse = sessionManager()->session()->getData(QLatin1String("syncTorrentPeersLastResponse")).toMap();
|
||||
auto lastAcceptedResponse = sessionManager()->session()->getData(QLatin1String("syncTorrentPeersLastAcceptedResponse")).toMap();
|
||||
|
||||
const auto hash = BitTorrent::InfoHash::fromString(params()["hash"]);
|
||||
const BitTorrent::Torrent *torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()["hash"]);
|
||||
const BitTorrent::Torrent *torrent = BitTorrent::Session::instance()->findTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
|
@ -120,18 +120,18 @@ namespace
|
||||
using Utils::String::parseInt;
|
||||
using Utils::String::parseDouble;
|
||||
|
||||
void applyToTorrents(const QStringList &hashes, const std::function<void (BitTorrent::Torrent *torrent)> &func)
|
||||
void applyToTorrents(const QStringList &idList, const std::function<void (BitTorrent::Torrent *torrent)> &func)
|
||||
{
|
||||
if ((hashes.size() == 1) && (hashes[0] == QLatin1String("all")))
|
||||
if ((idList.size() == 1) && (idList[0] == QLatin1String("all")))
|
||||
{
|
||||
for (BitTorrent::Torrent *const torrent : asConst(BitTorrent::Session::instance()->torrents()))
|
||||
func(torrent);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const QString &hashString : hashes)
|
||||
for (const QString &idString : idList)
|
||||
{
|
||||
const auto hash = BitTorrent::InfoHash::fromString(hashString);
|
||||
const auto hash = BitTorrent::TorrentID::fromString(idString);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
if (torrent)
|
||||
func(torrent);
|
||||
@ -211,20 +211,20 @@ namespace
|
||||
return {dht, pex, lsd};
|
||||
}
|
||||
|
||||
QVector<BitTorrent::InfoHash> toInfoHashes(const QStringList &hashes)
|
||||
QVector<BitTorrent::TorrentID> toTorrentIDs(const QStringList &idStrings)
|
||||
{
|
||||
QVector<BitTorrent::InfoHash> infoHashes;
|
||||
infoHashes.reserve(hashes.size());
|
||||
for (const QString &hash : hashes)
|
||||
infoHashes << BitTorrent::InfoHash::fromString(hash);
|
||||
return infoHashes;
|
||||
QVector<BitTorrent::TorrentID> idList;
|
||||
idList.reserve(idStrings.size());
|
||||
for (const QString &hash : idStrings)
|
||||
idList << BitTorrent::TorrentID::fromString(hash);
|
||||
return idList;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns all the torrents in JSON format.
|
||||
// The return value is a JSON-formatted list of dictionaries.
|
||||
// The dictionary keys are:
|
||||
// - "hash": Torrent hash
|
||||
// - "hash": Torrent hash (ID)
|
||||
// - "name": Torrent name
|
||||
// - "size": Torrent size
|
||||
// - "progress": Torrent progress
|
||||
@ -260,11 +260,11 @@ void TorrentsController::infoAction()
|
||||
int offset {params()["offset"].toInt()};
|
||||
const QStringList hashes {params()["hashes"].split('|', QString::SkipEmptyParts)};
|
||||
|
||||
InfoHashSet hashSet;
|
||||
TorrentIDSet idSet;
|
||||
for (const QString &hash : hashes)
|
||||
hashSet.insert(BitTorrent::InfoHash::fromString(hash));
|
||||
idSet.insert(BitTorrent::TorrentID::fromString(hash));
|
||||
|
||||
const TorrentFilter torrentFilter(filter, (hashes.isEmpty() ? TorrentFilter::AnyHash : hashSet), category);
|
||||
const TorrentFilter torrentFilter(filter, (hashes.isEmpty() ? TorrentFilter::AnyID : idSet), category);
|
||||
QVariantList torrentList;
|
||||
for (const BitTorrent::Torrent *torrent : asConst(BitTorrent::Session::instance()->torrents()))
|
||||
{
|
||||
@ -374,8 +374,8 @@ void TorrentsController::propertiesAction()
|
||||
{
|
||||
requireParams({"hash"});
|
||||
|
||||
const auto hash = BitTorrent::InfoHash::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
@ -445,8 +445,8 @@ void TorrentsController::trackersAction()
|
||||
{
|
||||
requireParams({"hash"});
|
||||
|
||||
const auto hash = BitTorrent::InfoHash::fromString(params()["hash"]);
|
||||
const BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()["hash"]);
|
||||
const BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
@ -481,8 +481,8 @@ void TorrentsController::webseedsAction()
|
||||
{
|
||||
requireParams({"hash"});
|
||||
|
||||
const auto hash = BitTorrent::InfoHash::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
@ -512,8 +512,8 @@ void TorrentsController::filesAction()
|
||||
{
|
||||
requireParams({"hash"});
|
||||
|
||||
const auto hash = BitTorrent::InfoHash::fromString(params()["hash"]);
|
||||
const BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()["hash"]);
|
||||
const BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
@ -558,8 +558,8 @@ void TorrentsController::pieceHashesAction()
|
||||
{
|
||||
requireParams({"hash"});
|
||||
|
||||
const auto hash = BitTorrent::InfoHash::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
@ -580,8 +580,8 @@ void TorrentsController::pieceStatesAction()
|
||||
{
|
||||
requireParams({"hash"});
|
||||
|
||||
const auto hash = BitTorrent::InfoHash::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
@ -691,8 +691,8 @@ void TorrentsController::addTrackersAction()
|
||||
{
|
||||
requireParams({"hash", "urls"});
|
||||
|
||||
const auto hash = BitTorrent::InfoHash::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
@ -710,11 +710,11 @@ void TorrentsController::editTrackerAction()
|
||||
{
|
||||
requireParams({"hash", "origUrl", "newUrl"});
|
||||
|
||||
const auto hash = BitTorrent::InfoHash::fromString(params()["hash"]);
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()["hash"]);
|
||||
const QString origUrl = params()["origUrl"];
|
||||
const QString newUrl = params()["newUrl"];
|
||||
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
@ -751,8 +751,8 @@ void TorrentsController::removeTrackersAction()
|
||||
{
|
||||
requireParams({"hash", "urls"});
|
||||
|
||||
const auto hash = BitTorrent::InfoHash::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
@ -804,7 +804,7 @@ void TorrentsController::addPeersAction()
|
||||
return torrent->connectPeer(peer);
|
||||
});
|
||||
|
||||
results[torrent->hash().toString()] = QJsonObject
|
||||
results[torrent->id().toString()] = QJsonObject
|
||||
{
|
||||
{"added", peersAdded},
|
||||
{"failed", (peers.size() - peersAdded)}
|
||||
@ -826,15 +826,15 @@ void TorrentsController::resumeAction()
|
||||
{
|
||||
requireParams({"hashes"});
|
||||
|
||||
const QStringList hashes = params()["hashes"].split('|');
|
||||
applyToTorrents(hashes, [](BitTorrent::Torrent *const torrent) { torrent->resume(); });
|
||||
const QStringList idStrings = params()["hashes"].split('|');
|
||||
applyToTorrents(idStrings, [](BitTorrent::Torrent *const torrent) { torrent->resume(); });
|
||||
}
|
||||
|
||||
void TorrentsController::filePrioAction()
|
||||
{
|
||||
requireParams({"hash", "id", "priority"});
|
||||
|
||||
const auto hash = BitTorrent::InfoHash::fromString(params()["hash"]);
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()["hash"]);
|
||||
bool ok = false;
|
||||
const auto priority = static_cast<BitTorrent::DownloadPriority>(params()["priority"].toInt(&ok));
|
||||
if (!ok)
|
||||
@ -843,7 +843,7 @@ void TorrentsController::filePrioAction()
|
||||
if (!BitTorrent::isValidDownloadPriority(priority))
|
||||
throw APIError(APIErrorType::BadParams, tr("Priority is not valid"));
|
||||
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
if (!torrent->hasMetadata())
|
||||
@ -875,15 +875,15 @@ void TorrentsController::uploadLimitAction()
|
||||
{
|
||||
requireParams({"hashes"});
|
||||
|
||||
const QStringList hashes {params()["hashes"].split('|')};
|
||||
const QStringList idList {params()["hashes"].split('|')};
|
||||
QJsonObject map;
|
||||
for (const QString &hash : hashes)
|
||||
for (const QString &id : idList)
|
||||
{
|
||||
int limit = -1;
|
||||
const BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(BitTorrent::InfoHash::fromString(hash));
|
||||
const BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(BitTorrent::TorrentID::fromString(id));
|
||||
if (torrent)
|
||||
limit = torrent->uploadLimit();
|
||||
map[hash] = limit;
|
||||
map[id] = limit;
|
||||
}
|
||||
|
||||
setResult(map);
|
||||
@ -893,15 +893,15 @@ void TorrentsController::downloadLimitAction()
|
||||
{
|
||||
requireParams({"hashes"});
|
||||
|
||||
const QStringList hashes {params()["hashes"].split('|')};
|
||||
const QStringList idList {params()["hashes"].split('|')};
|
||||
QJsonObject map;
|
||||
for (const QString &hash : hashes)
|
||||
for (const QString &id : idList)
|
||||
{
|
||||
int limit = -1;
|
||||
const BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(BitTorrent::InfoHash::fromString(hash));
|
||||
const BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(BitTorrent::TorrentID::fromString(id));
|
||||
if (torrent)
|
||||
limit = torrent->downloadLimit();
|
||||
map[hash] = limit;
|
||||
map[id] = limit;
|
||||
}
|
||||
|
||||
setResult(map);
|
||||
@ -992,7 +992,7 @@ void TorrentsController::deleteAction()
|
||||
? DeleteTorrentAndFiles : DeleteTorrent;
|
||||
applyToTorrents(hashes, [deleteOption](const BitTorrent::Torrent *torrent)
|
||||
{
|
||||
BitTorrent::Session::instance()->deleteTorrent(torrent->hash(), deleteOption);
|
||||
BitTorrent::Session::instance()->deleteTorrent(torrent->id(), deleteOption);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1004,7 +1004,7 @@ void TorrentsController::increasePrioAction()
|
||||
throw APIError(APIErrorType::Conflict, tr("Torrent queueing must be enabled"));
|
||||
|
||||
const QStringList hashes {params()["hashes"].split('|')};
|
||||
BitTorrent::Session::instance()->increaseTorrentsQueuePos(toInfoHashes(hashes));
|
||||
BitTorrent::Session::instance()->increaseTorrentsQueuePos(toTorrentIDs(hashes));
|
||||
}
|
||||
|
||||
void TorrentsController::decreasePrioAction()
|
||||
@ -1015,7 +1015,7 @@ void TorrentsController::decreasePrioAction()
|
||||
throw APIError(APIErrorType::Conflict, tr("Torrent queueing must be enabled"));
|
||||
|
||||
const QStringList hashes {params()["hashes"].split('|')};
|
||||
BitTorrent::Session::instance()->decreaseTorrentsQueuePos(toInfoHashes(hashes));
|
||||
BitTorrent::Session::instance()->decreaseTorrentsQueuePos(toTorrentIDs(hashes));
|
||||
}
|
||||
|
||||
void TorrentsController::topPrioAction()
|
||||
@ -1026,7 +1026,7 @@ void TorrentsController::topPrioAction()
|
||||
throw APIError(APIErrorType::Conflict, tr("Torrent queueing must be enabled"));
|
||||
|
||||
const QStringList hashes {params()["hashes"].split('|')};
|
||||
BitTorrent::Session::instance()->topTorrentsQueuePos(toInfoHashes(hashes));
|
||||
BitTorrent::Session::instance()->topTorrentsQueuePos(toTorrentIDs(hashes));
|
||||
}
|
||||
|
||||
void TorrentsController::bottomPrioAction()
|
||||
@ -1037,7 +1037,7 @@ void TorrentsController::bottomPrioAction()
|
||||
throw APIError(APIErrorType::Conflict, tr("Torrent queueing must be enabled"));
|
||||
|
||||
const QStringList hashes {params()["hashes"].split('|')};
|
||||
BitTorrent::Session::instance()->bottomTorrentsQueuePos(toInfoHashes(hashes));
|
||||
BitTorrent::Session::instance()->bottomTorrentsQueuePos(toTorrentIDs(hashes));
|
||||
}
|
||||
|
||||
void TorrentsController::setLocationAction()
|
||||
@ -1070,13 +1070,13 @@ void TorrentsController::renameAction()
|
||||
{
|
||||
requireParams({"hash", "name"});
|
||||
|
||||
const auto hash = BitTorrent::InfoHash::fromString(params()["hash"]);
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()["hash"]);
|
||||
QString name = params()["name"].trimmed();
|
||||
|
||||
if (name.isEmpty())
|
||||
throw APIError(APIErrorType::Conflict, tr("Incorrect torrent name"));
|
||||
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
@ -1257,8 +1257,8 @@ void TorrentsController::renameFileAction()
|
||||
{
|
||||
requireParams({"hash", "oldPath", "newPath"});
|
||||
|
||||
const auto hash = BitTorrent::InfoHash::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
@ -1279,8 +1279,8 @@ void TorrentsController::renameFolderAction()
|
||||
{
|
||||
requireParams({"hash", "oldPath", "newPath"});
|
||||
|
||||
const auto hash = BitTorrent::InfoHash::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()["hash"]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->findTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user