mirror of
https://github.com/qbittorrent/qBittorrent
synced 2024-11-03 00:09:23 +01:00
Merge pull request #10373 from glassez/libtorrent-1.2
Add preliminary support of libtorrent v1.2
This commit is contained in:
commit
6de02b0f2a
@ -4,12 +4,14 @@ add_library(qbt_base STATIC
|
|||||||
# headers
|
# headers
|
||||||
bittorrent/addtorrentparams.h
|
bittorrent/addtorrentparams.h
|
||||||
bittorrent/cachestatus.h
|
bittorrent/cachestatus.h
|
||||||
bittorrent/filepriority.h
|
bittorrent/downloadpriority.h
|
||||||
bittorrent/infohash.h
|
bittorrent/infohash.h
|
||||||
bittorrent/magneturi.h
|
bittorrent/magneturi.h
|
||||||
bittorrent/peerinfo.h
|
bittorrent/peerinfo.h
|
||||||
bittorrent/private/bandwidthscheduler.h
|
bittorrent/private/bandwidthscheduler.h
|
||||||
|
bittorrent/private/libtorrentfwd.h
|
||||||
bittorrent/private/filterparserthread.h
|
bittorrent/private/filterparserthread.h
|
||||||
|
bittorrent/private/portforwarderimpl.h
|
||||||
bittorrent/private/resumedatasavingmanager.h
|
bittorrent/private/resumedatasavingmanager.h
|
||||||
bittorrent/private/speedmonitor.h
|
bittorrent/private/speedmonitor.h
|
||||||
bittorrent/private/statistics.h
|
bittorrent/private/statistics.h
|
||||||
@ -77,12 +79,13 @@ types.h
|
|||||||
unicodestrings.h
|
unicodestrings.h
|
||||||
|
|
||||||
# sources
|
# sources
|
||||||
bittorrent/filepriority.cpp
|
bittorrent/downloadpriority.cpp
|
||||||
bittorrent/infohash.cpp
|
bittorrent/infohash.cpp
|
||||||
bittorrent/magneturi.cpp
|
bittorrent/magneturi.cpp
|
||||||
bittorrent/peerinfo.cpp
|
bittorrent/peerinfo.cpp
|
||||||
bittorrent/private/bandwidthscheduler.cpp
|
bittorrent/private/bandwidthscheduler.cpp
|
||||||
bittorrent/private/filterparserthread.cpp
|
bittorrent/private/filterparserthread.cpp
|
||||||
|
bittorrent/private/portforwarderimpl.cpp
|
||||||
bittorrent/private/resumedatasavingmanager.cpp
|
bittorrent/private/resumedatasavingmanager.cpp
|
||||||
bittorrent/private/speedmonitor.cpp
|
bittorrent/private/speedmonitor.cpp
|
||||||
bittorrent/private/statistics.cpp
|
bittorrent/private/statistics.cpp
|
||||||
|
@ -3,12 +3,14 @@ HEADERS += \
|
|||||||
$$PWD/asyncfilestorage.h \
|
$$PWD/asyncfilestorage.h \
|
||||||
$$PWD/bittorrent/addtorrentparams.h \
|
$$PWD/bittorrent/addtorrentparams.h \
|
||||||
$$PWD/bittorrent/cachestatus.h \
|
$$PWD/bittorrent/cachestatus.h \
|
||||||
$$PWD/bittorrent/filepriority.h \
|
$$PWD/bittorrent/downloadpriority.h \
|
||||||
$$PWD/bittorrent/infohash.h \
|
$$PWD/bittorrent/infohash.h \
|
||||||
$$PWD/bittorrent/magneturi.h \
|
$$PWD/bittorrent/magneturi.h \
|
||||||
$$PWD/bittorrent/peerinfo.h \
|
$$PWD/bittorrent/peerinfo.h \
|
||||||
$$PWD/bittorrent/private/bandwidthscheduler.h \
|
$$PWD/bittorrent/private/bandwidthscheduler.h \
|
||||||
$$PWD/bittorrent/private/filterparserthread.h \
|
$$PWD/bittorrent/private/filterparserthread.h \
|
||||||
|
$$PWD/bittorrent/private/libtorrentfwd.h \
|
||||||
|
$$PWD/bittorrent/private/portforwarderimpl.h \
|
||||||
$$PWD/bittorrent/private/resumedatasavingmanager.h \
|
$$PWD/bittorrent/private/resumedatasavingmanager.h \
|
||||||
$$PWD/bittorrent/private/speedmonitor.h \
|
$$PWD/bittorrent/private/speedmonitor.h \
|
||||||
$$PWD/bittorrent/private/statistics.h \
|
$$PWD/bittorrent/private/statistics.h \
|
||||||
@ -76,12 +78,13 @@ HEADERS += \
|
|||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/asyncfilestorage.cpp \
|
$$PWD/asyncfilestorage.cpp \
|
||||||
$$PWD/bittorrent/filepriority.cpp \
|
$$PWD/bittorrent/downloadpriority.cpp \
|
||||||
$$PWD/bittorrent/infohash.cpp \
|
$$PWD/bittorrent/infohash.cpp \
|
||||||
$$PWD/bittorrent/magneturi.cpp \
|
$$PWD/bittorrent/magneturi.cpp \
|
||||||
$$PWD/bittorrent/peerinfo.cpp \
|
$$PWD/bittorrent/peerinfo.cpp \
|
||||||
$$PWD/bittorrent/private/bandwidthscheduler.cpp \
|
$$PWD/bittorrent/private/bandwidthscheduler.cpp \
|
||||||
$$PWD/bittorrent/private/filterparserthread.cpp \
|
$$PWD/bittorrent/private/filterparserthread.cpp \
|
||||||
|
$$PWD/bittorrent/private/portforwarderimpl.cpp \
|
||||||
$$PWD/bittorrent/private/resumedatasavingmanager.cpp \
|
$$PWD/bittorrent/private/resumedatasavingmanager.cpp \
|
||||||
$$PWD/bittorrent/private/speedmonitor.cpp \
|
$$PWD/bittorrent/private/speedmonitor.cpp \
|
||||||
$$PWD/bittorrent/private/statistics.cpp \
|
$$PWD/bittorrent/private/statistics.cpp \
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
#include "../tristatebool.h"
|
#include "../tristatebool.h"
|
||||||
|
#include "downloadpriority.h"
|
||||||
|
|
||||||
namespace BitTorrent
|
namespace BitTorrent
|
||||||
{
|
{
|
||||||
@ -47,7 +48,7 @@ namespace BitTorrent
|
|||||||
bool firstLastPiecePriority = false;
|
bool firstLastPiecePriority = false;
|
||||||
TriStateBool addForced;
|
TriStateBool addForced;
|
||||||
TriStateBool addPaused;
|
TriStateBool addPaused;
|
||||||
QVector<int> filePriorities; // used if TorrentInfo is set
|
QVector<DownloadPriority> filePriorities; // used if TorrentInfo is set
|
||||||
bool ignoreShareLimits = false;
|
bool ignoreShareLimits = false;
|
||||||
bool skipChecking = false;
|
bool skipChecking = false;
|
||||||
TriStateBool createSubfolder;
|
TriStateBool createSubfolder;
|
||||||
|
@ -26,18 +26,18 @@
|
|||||||
* exception statement from your version.
|
* exception statement from your version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "filepriority.h"
|
#include "downloadpriority.h"
|
||||||
|
|
||||||
namespace BitTorrent
|
namespace BitTorrent
|
||||||
{
|
{
|
||||||
bool isValidFilePriority(const BitTorrent::FilePriority priority)
|
bool isValidDownloadPriority(const DownloadPriority priority)
|
||||||
{
|
{
|
||||||
switch (priority) {
|
switch (priority) {
|
||||||
case BitTorrent::FilePriority::Ignored:
|
case BitTorrent::DownloadPriority::Ignored:
|
||||||
case BitTorrent::FilePriority::Normal:
|
case BitTorrent::DownloadPriority::Normal:
|
||||||
case BitTorrent::FilePriority::High:
|
case BitTorrent::DownloadPriority::High:
|
||||||
case BitTorrent::FilePriority::Maximum:
|
case BitTorrent::DownloadPriority::Maximum:
|
||||||
case BitTorrent::FilePriority::Mixed:
|
case BitTorrent::DownloadPriority::Mixed:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
@ -30,14 +30,15 @@
|
|||||||
|
|
||||||
namespace BitTorrent
|
namespace BitTorrent
|
||||||
{
|
{
|
||||||
enum class FilePriority : int
|
enum class DownloadPriority : int
|
||||||
{
|
{
|
||||||
Ignored = 0,
|
Ignored = 0,
|
||||||
Normal = 1,
|
Normal = 1,
|
||||||
High = 6,
|
High = 6,
|
||||||
Maximum = 7,
|
Maximum = 7,
|
||||||
|
|
||||||
Mixed = -1
|
Mixed = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
bool isValidFilePriority(BitTorrent::FilePriority priority);
|
bool isValidDownloadPriority(DownloadPriority priority);
|
||||||
}
|
}
|
@ -42,18 +42,18 @@ InfoHash::InfoHash(const libtorrent::sha1_hash &nativeHash)
|
|||||||
: m_valid(true)
|
: m_valid(true)
|
||||||
, m_nativeHash(nativeHash)
|
, m_nativeHash(nativeHash)
|
||||||
{
|
{
|
||||||
const QByteArray raw = QByteArray::fromRawData(nativeHash.data(), libtorrent::sha1_hash::size);
|
const QByteArray raw = QByteArray::fromRawData(nativeHash.data(), length());
|
||||||
m_hashString = QString::fromLatin1(raw.toHex());
|
m_hashString = QString::fromLatin1(raw.toHex());
|
||||||
}
|
}
|
||||||
|
|
||||||
InfoHash::InfoHash(const QString &hashString)
|
InfoHash::InfoHash(const QString &hashString)
|
||||||
: m_valid(false)
|
: m_valid(false)
|
||||||
{
|
{
|
||||||
if (hashString.size() != (libtorrent::sha1_hash::size * 2))
|
if (hashString.size() != (length() * 2))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QByteArray raw = QByteArray::fromHex(hashString.toLatin1());
|
const QByteArray raw = QByteArray::fromHex(hashString.toLatin1());
|
||||||
if (raw.size() != libtorrent::sha1_hash::size) // QByteArray::fromHex() will skip over invalid characters
|
if (raw.size() != length()) // QByteArray::fromHex() will skip over invalid characters
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_valid = true;
|
m_valid = true;
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
#define BITTORRENT_INFOHASH_H
|
#define BITTORRENT_INFOHASH_H
|
||||||
|
|
||||||
#include <libtorrent/sha1_hash.hpp>
|
#include <libtorrent/sha1_hash.hpp>
|
||||||
|
#include <libtorrent/version.hpp>
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
namespace BitTorrent
|
namespace BitTorrent
|
||||||
@ -42,6 +44,15 @@ namespace BitTorrent
|
|||||||
InfoHash(const QString &hashString);
|
InfoHash(const QString &hashString);
|
||||||
InfoHash(const InfoHash &other) = default;
|
InfoHash(const InfoHash &other) = default;
|
||||||
|
|
||||||
|
static constexpr int length()
|
||||||
|
{
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
return libtorrent::sha1_hash::size;
|
||||||
|
#else
|
||||||
|
return libtorrent::sha1_hash::size();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
operator libtorrent::sha1_hash() const;
|
operator libtorrent::sha1_hash() const;
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
|
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
#include "infohash.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
bool isBitTorrentInfoHash(const QString &string)
|
bool isBitTorrentInfoHash(const QString &string)
|
||||||
@ -44,8 +46,8 @@ namespace
|
|||||||
// == 20 (SHA-1 length in bytes) * 2 (each byte maps to 2 hex characters)
|
// == 20 (SHA-1 length in bytes) * 2 (each byte maps to 2 hex characters)
|
||||||
// 2. 32 chars Base32 encoded string
|
// 2. 32 chars Base32 encoded string
|
||||||
// == 20 (SHA-1 length in bytes) * 1.6 (the efficiency of Base32 encoding)
|
// == 20 (SHA-1 length in bytes) * 1.6 (the efficiency of Base32 encoding)
|
||||||
const int SHA1_HEX_SIZE = libtorrent::sha1_hash::size * 2;
|
const int SHA1_HEX_SIZE = BitTorrent::InfoHash::length() * 2;
|
||||||
const int SHA1_BASE32_SIZE = libtorrent::sha1_hash::size * 1.6;
|
const int SHA1_BASE32_SIZE = BitTorrent::InfoHash::length() * 1.6;
|
||||||
|
|
||||||
return ((((string.size() == SHA1_HEX_SIZE))
|
return ((((string.size() == SHA1_HEX_SIZE))
|
||||||
&& !string.contains(QRegularExpression(QLatin1String("[^0-9A-Fa-f]"))))
|
&& !string.contains(QRegularExpression(QLatin1String("[^0-9A-Fa-f]"))))
|
||||||
@ -75,7 +77,7 @@ MagnetUri::MagnetUri(const QString &source)
|
|||||||
m_name = QString::fromStdString(m_addTorrentParams.name);
|
m_name = QString::fromStdString(m_addTorrentParams.name);
|
||||||
|
|
||||||
for (const std::string &tracker : m_addTorrentParams.trackers)
|
for (const std::string &tracker : m_addTorrentParams.trackers)
|
||||||
m_trackers.append(TrackerEntry(tracker));
|
m_trackers.append(libtorrent::announce_entry {tracker});
|
||||||
|
|
||||||
for (const std::string &urlSeed : m_addTorrentParams.url_seeds)
|
for (const std::string &urlSeed : m_addTorrentParams.url_seeds)
|
||||||
m_urlSeeds.append(QUrl(QString::fromStdString(urlSeed)));
|
m_urlSeeds.append(QUrl(QString::fromStdString(urlSeed)));
|
||||||
|
@ -60,17 +60,17 @@ PeerInfo::PeerInfo(const TorrentHandle *torrent, const libt::peer_info &nativeIn
|
|||||||
|
|
||||||
bool PeerInfo::fromDHT() const
|
bool PeerInfo::fromDHT() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.source & libt::peer_info::dht);
|
return static_cast<bool>(m_nativeInfo.source & libt::peer_info::dht);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::fromPeX() const
|
bool PeerInfo::fromPeX() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.source & libt::peer_info::pex);
|
return static_cast<bool>(m_nativeInfo.source & libt::peer_info::pex);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::fromLSD() const
|
bool PeerInfo::fromLSD() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.source & libt::peer_info::lsd);
|
return static_cast<bool>(m_nativeInfo.source & libt::peer_info::lsd);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||||
@ -82,102 +82,102 @@ QString PeerInfo::country() const
|
|||||||
|
|
||||||
bool PeerInfo::isInteresting() const
|
bool PeerInfo::isInteresting() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::interesting);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::interesting);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::isChocked() const
|
bool PeerInfo::isChocked() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::choked);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::choked);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::isRemoteInterested() const
|
bool PeerInfo::isRemoteInterested() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::remote_interested);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::remote_interested);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::isRemoteChocked() const
|
bool PeerInfo::isRemoteChocked() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::remote_choked);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::remote_choked);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::isSupportsExtensions() const
|
bool PeerInfo::isSupportsExtensions() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::supports_extensions);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::supports_extensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::isLocalConnection() const
|
bool PeerInfo::isLocalConnection() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::local_connection);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::local_connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::isHandshake() const
|
bool PeerInfo::isHandshake() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::handshake);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::handshake);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::isConnecting() const
|
bool PeerInfo::isConnecting() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::connecting);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::connecting);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::isOnParole() const
|
bool PeerInfo::isOnParole() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::on_parole);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::on_parole);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::isSeed() const
|
bool PeerInfo::isSeed() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::seed);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::optimisticUnchoke() const
|
bool PeerInfo::optimisticUnchoke() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::optimistic_unchoke);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::optimistic_unchoke);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::isSnubbed() const
|
bool PeerInfo::isSnubbed() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::snubbed);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::snubbed);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::isUploadOnly() const
|
bool PeerInfo::isUploadOnly() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::upload_only);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::upload_only);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::isEndgameMode() const
|
bool PeerInfo::isEndgameMode() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::endgame_mode);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::endgame_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::isHolepunched() const
|
bool PeerInfo::isHolepunched() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::holepunched);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::holepunched);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::useI2PSocket() const
|
bool PeerInfo::useI2PSocket() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::i2p_socket);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::i2p_socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::useUTPSocket() const
|
bool PeerInfo::useUTPSocket() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::utp_socket);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::utp_socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::useSSLSocket() const
|
bool PeerInfo::useSSLSocket() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::ssl_socket);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::ssl_socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::isRC4Encrypted() const
|
bool PeerInfo::isRC4Encrypted() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::rc4_encrypted);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::rc4_encrypted);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerInfo::isPlaintextEncrypted() const
|
bool PeerInfo::isPlaintextEncrypted() const
|
||||||
{
|
{
|
||||||
return (m_nativeInfo.flags & libt::peer_info::plaintext_encrypted);
|
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::plaintext_encrypted);
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerAddress PeerInfo::address() const
|
PeerAddress PeerInfo::address() const
|
||||||
@ -220,8 +220,9 @@ QBitArray PeerInfo::pieces() const
|
|||||||
{
|
{
|
||||||
QBitArray result(m_nativeInfo.pieces.size());
|
QBitArray result(m_nativeInfo.pieces.size());
|
||||||
|
|
||||||
for (int i = 0; i < m_nativeInfo.pieces.size(); ++i)
|
int i = 0;
|
||||||
result.setBit(i, m_nativeInfo.pieces.get_bit(i));
|
for (const bool bit : m_nativeInfo.pieces)
|
||||||
|
result.setBit(i++, bit);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -397,5 +398,5 @@ QString PeerInfo::flagsDescription() const
|
|||||||
|
|
||||||
int PeerInfo::downloadingPieceIndex() const
|
int PeerInfo::downloadingPieceIndex() const
|
||||||
{
|
{
|
||||||
return m_nativeInfo.downloading_piece_index;
|
return static_cast<int>(m_nativeInfo.downloading_piece_index);
|
||||||
}
|
}
|
||||||
|
81
src/base/bittorrent/private/libtorrentfwd.h
Normal file
81
src/base/bittorrent/private/libtorrentfwd.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2019 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give permission to
|
||||||
|
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||||
|
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||||
|
* and distribute the linked executables. You must obey the GNU General Public
|
||||||
|
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||||
|
* modify file(s), you may extend this exception to your version of the file(s),
|
||||||
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
|
* exception statement from your version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libtorrent/version.hpp>
|
||||||
|
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
namespace libtorrent
|
||||||
|
{
|
||||||
|
class entry;
|
||||||
|
class session;
|
||||||
|
struct ip_filter;
|
||||||
|
struct settings_pack;
|
||||||
|
struct torrent_handle;
|
||||||
|
|
||||||
|
class alert;
|
||||||
|
struct add_torrent_alert;
|
||||||
|
struct external_ip_alert;
|
||||||
|
struct fastresume_rejected_alert;
|
||||||
|
struct file_completed_alert;
|
||||||
|
struct file_error_alert;
|
||||||
|
struct file_rename_failed_alert;
|
||||||
|
struct file_renamed_alert;
|
||||||
|
struct listen_failed_alert;
|
||||||
|
struct listen_succeeded_alert;
|
||||||
|
struct metadata_received_alert;
|
||||||
|
struct peer_ban_alert;
|
||||||
|
struct peer_blocked_alert;
|
||||||
|
struct portmap_alert;
|
||||||
|
struct portmap_error_alert;
|
||||||
|
struct save_resume_data_alert;
|
||||||
|
struct save_resume_data_failed_alert;
|
||||||
|
struct session_stats_alert;
|
||||||
|
struct state_update_alert;
|
||||||
|
struct stats_alert;
|
||||||
|
struct storage_moved_alert;
|
||||||
|
struct storage_moved_failed_alert;
|
||||||
|
struct torrent_alert;
|
||||||
|
struct torrent_checked_alert;
|
||||||
|
struct torrent_delete_failed_alert;
|
||||||
|
struct torrent_deleted_alert;
|
||||||
|
struct torrent_finished_alert;
|
||||||
|
struct torrent_paused_alert;
|
||||||
|
struct torrent_removed_alert;
|
||||||
|
struct torrent_resumed_alert;
|
||||||
|
struct tracker_error_alert;
|
||||||
|
struct tracker_reply_alert;
|
||||||
|
struct tracker_warning_alert;
|
||||||
|
struct url_seed_alert;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace lt = libtorrent;
|
||||||
|
#else
|
||||||
|
#include <libtorrent/fwd.hpp>
|
||||||
|
#endif
|
114
src/base/bittorrent/private/portforwarderimpl.cpp
Normal file
114
src/base/bittorrent/private/portforwarderimpl.cpp
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2019 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give permission to
|
||||||
|
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||||
|
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||||
|
* and distribute the linked executables. You must obey the GNU General Public
|
||||||
|
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||||
|
* modify file(s), you may extend this exception to your version of the file(s),
|
||||||
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
|
* exception statement from your version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "portforwarderimpl.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include <libtorrent/session.hpp>
|
||||||
|
|
||||||
|
#include "base/logger.h"
|
||||||
|
#include "base/settingsstorage.h"
|
||||||
|
|
||||||
|
const QString KEY_ENABLED = QStringLiteral("Network/PortForwardingEnabled");
|
||||||
|
|
||||||
|
PortForwarderImpl::PortForwarderImpl(libtorrent::session *provider, QObject *parent)
|
||||||
|
: Net::PortForwarder {parent}
|
||||||
|
, m_active {SettingsStorage::instance()->loadValue(KEY_ENABLED, true).toBool()}
|
||||||
|
, m_provider {provider}
|
||||||
|
{
|
||||||
|
if (m_active)
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
PortForwarderImpl::~PortForwarderImpl()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PortForwarderImpl::isEnabled() const
|
||||||
|
{
|
||||||
|
return m_active;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PortForwarderImpl::setEnabled(const bool enabled)
|
||||||
|
{
|
||||||
|
if (m_active != enabled) {
|
||||||
|
if (enabled)
|
||||||
|
start();
|
||||||
|
else
|
||||||
|
stop();
|
||||||
|
|
||||||
|
m_active = enabled;
|
||||||
|
SettingsStorage::instance()->storeValue(KEY_ENABLED, enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PortForwarderImpl::addPort(const quint16 port)
|
||||||
|
{
|
||||||
|
if (!m_mappedPorts.contains(port)) {
|
||||||
|
m_mappedPorts.insert(port, {});
|
||||||
|
if (isEnabled())
|
||||||
|
m_mappedPorts[port] = {m_provider->add_port_mapping(lt::session::tcp, port, port)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PortForwarderImpl::deletePort(const quint16 port)
|
||||||
|
{
|
||||||
|
if (m_mappedPorts.contains(port)) {
|
||||||
|
if (isEnabled()) {
|
||||||
|
for (const LTPortMapping &portMapping : m_mappedPorts[port])
|
||||||
|
m_provider->delete_port_mapping(portMapping);
|
||||||
|
}
|
||||||
|
m_mappedPorts.remove(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PortForwarderImpl::start()
|
||||||
|
{
|
||||||
|
qDebug("Enabling UPnP / NAT-PMP");
|
||||||
|
lt::settings_pack settingsPack = m_provider->get_settings();
|
||||||
|
settingsPack.set_bool(lt::settings_pack::enable_upnp, true);
|
||||||
|
settingsPack.set_bool(lt::settings_pack::enable_natpmp, true);
|
||||||
|
m_provider->apply_settings(settingsPack);
|
||||||
|
for (auto i = m_mappedPorts.begin(); i != m_mappedPorts.end(); ++i) {
|
||||||
|
// quint16 port = i.key();
|
||||||
|
i.value() = {m_provider->add_port_mapping(lt::session::tcp, i.key(), i.key())};
|
||||||
|
}
|
||||||
|
LogMsg(tr("UPnP / NAT-PMP support [ON]"), Log::INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PortForwarderImpl::stop()
|
||||||
|
{
|
||||||
|
qDebug("Disabling UPnP / NAT-PMP");
|
||||||
|
lt::settings_pack settingsPack = m_provider->get_settings();
|
||||||
|
settingsPack.set_bool(lt::settings_pack::enable_upnp, false);
|
||||||
|
settingsPack.set_bool(lt::settings_pack::enable_natpmp, false);
|
||||||
|
m_provider->apply_settings(settingsPack);
|
||||||
|
LogMsg(tr("UPnP / NAT-PMP support [OFF]"), Log::INFO);
|
||||||
|
}
|
65
src/base/bittorrent/private/portforwarderimpl.h
Normal file
65
src/base/bittorrent/private/portforwarderimpl.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
|
* Copyright (C) 2019 Vladimir Golovnev <glassez@yandex.ru>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* In addition, as a special exception, the copyright holders give permission to
|
||||||
|
* link this program with the OpenSSL project's "OpenSSL" library (or with
|
||||||
|
* modified versions of it that use the same license as the "OpenSSL" library),
|
||||||
|
* and distribute the linked executables. You must obey the GNU General Public
|
||||||
|
* License in all respects for all of the code used other than "OpenSSL". If you
|
||||||
|
* modify file(s), you may extend this exception to your version of the file(s),
|
||||||
|
* but you are not obligated to do so. If you do not wish to do so, delete this
|
||||||
|
* exception statement from your version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
|
#include "base/net/portforwarder.h"
|
||||||
|
#include "libtorrentfwd.h"
|
||||||
|
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
using LTPortMapping = int;
|
||||||
|
#else
|
||||||
|
#include <libtorrent/portmap.hpp>
|
||||||
|
using LTPortMapping = lt::port_mapping_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class PortForwarderImpl : public Net::PortForwarder
|
||||||
|
{
|
||||||
|
Q_DISABLE_COPY(PortForwarderImpl)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit PortForwarderImpl(lt::session *provider, QObject *parent = nullptr);
|
||||||
|
~PortForwarderImpl() override;
|
||||||
|
|
||||||
|
bool isEnabled() const override;
|
||||||
|
void setEnabled(bool enabled) override;
|
||||||
|
|
||||||
|
void addPort(quint16 port) override;
|
||||||
|
void deletePort(quint16 port) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
bool m_active;
|
||||||
|
libtorrent::session *m_provider;
|
||||||
|
QHash<quint16, std::vector<LTPortMapping>> m_mappedPorts;
|
||||||
|
};
|
@ -62,13 +62,13 @@
|
|||||||
#include <libtorrent/session_stats.hpp>
|
#include <libtorrent/session_stats.hpp>
|
||||||
#include <libtorrent/session_status.hpp>
|
#include <libtorrent/session_status.hpp>
|
||||||
#include <libtorrent/torrent_info.hpp>
|
#include <libtorrent/torrent_info.hpp>
|
||||||
|
#include <libtorrent/version.hpp>
|
||||||
|
|
||||||
#include "base/algorithm.h"
|
#include "base/algorithm.h"
|
||||||
#include "base/exceptions.h"
|
#include "base/exceptions.h"
|
||||||
#include "base/global.h"
|
#include "base/global.h"
|
||||||
#include "base/logger.h"
|
#include "base/logger.h"
|
||||||
#include "base/net/downloadmanager.h"
|
#include "base/net/downloadmanager.h"
|
||||||
#include "base/net/portforwarder.h"
|
|
||||||
#include "base/net/proxyconfigurationmanager.h"
|
#include "base/net/proxyconfigurationmanager.h"
|
||||||
#include "base/profile.h"
|
#include "base/profile.h"
|
||||||
#include "base/torrentfileguard.h"
|
#include "base/torrentfileguard.h"
|
||||||
@ -82,6 +82,7 @@
|
|||||||
#include "magneturi.h"
|
#include "magneturi.h"
|
||||||
#include "private/bandwidthscheduler.h"
|
#include "private/bandwidthscheduler.h"
|
||||||
#include "private/filterparserthread.h"
|
#include "private/filterparserthread.h"
|
||||||
|
#include "private/portforwarderimpl.h"
|
||||||
#include "private/resumedatasavingmanager.h"
|
#include "private/resumedatasavingmanager.h"
|
||||||
#include "private/statistics.h"
|
#include "private/statistics.h"
|
||||||
#include "torrenthandle.h"
|
#include "torrenthandle.h"
|
||||||
@ -106,6 +107,16 @@ using namespace BitTorrent;
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
using LTSessionFlags = int;
|
||||||
|
using LTStatusFlags = int;
|
||||||
|
using LTString = std::string;
|
||||||
|
#else
|
||||||
|
using LTSessionFlags = lt::session_flags_t;
|
||||||
|
using LTStatusFlags = lt::status_flags_t;
|
||||||
|
using LTString = lt::string_view;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool readFile(const QString &path, QByteArray &buf);
|
bool readFile(const QString &path, QByteArray &buf);
|
||||||
bool loadTorrentResumeData(const QByteArray &data, CreateTorrentParams &torrentParams, int &prio, MagnetUri &magnetUri);
|
bool loadTorrentResumeData(const QByteArray &data, CreateTorrentParams &torrentParams, int &prio, MagnetUri &magnetUri);
|
||||||
|
|
||||||
@ -134,13 +145,19 @@ namespace
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename LTStr>
|
||||||
|
QString fromLTString(const LTStr &str)
|
||||||
|
{
|
||||||
|
return QString::fromUtf8(str.data(), static_cast<int>(str.size()));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Entry>
|
template <typename Entry>
|
||||||
QSet<QString> entryListToSetImpl(const Entry &entry)
|
QSet<QString> entryListToSetImpl(const Entry &entry)
|
||||||
{
|
{
|
||||||
Q_ASSERT(entry.type() == Entry::list_t);
|
Q_ASSERT(entry.type() == Entry::list_t);
|
||||||
QSet<QString> output;
|
QSet<QString> output;
|
||||||
for (int i = 0; i < entry.list_size(); ++i) {
|
for (int i = 0; i < entry.list_size(); ++i) {
|
||||||
const QString tag = QString::fromStdString(entry.list_string_value_at(i));
|
const QString tag = fromLTString(entry.list_string_value_at(i));
|
||||||
if (Session::isValidTag(tag))
|
if (Session::isValidTag(tag))
|
||||||
output.insert(tag);
|
output.insert(tag);
|
||||||
else
|
else
|
||||||
@ -405,7 +422,7 @@ Session::Session(QObject *parent)
|
|||||||
pack.set_bool(libt::settings_pack::upnp_ignore_nonrouters, true);
|
pack.set_bool(libt::settings_pack::upnp_ignore_nonrouters, true);
|
||||||
configure(pack);
|
configure(pack);
|
||||||
|
|
||||||
m_nativeSession = new libt::session(pack, 0);
|
m_nativeSession = new lt::session {pack, LTSessionFlags {0}};
|
||||||
m_nativeSession->set_alert_notify([this]()
|
m_nativeSession->set_alert_notify([this]()
|
||||||
{
|
{
|
||||||
QMetaObject::invokeMethod(this, "readAlerts", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(this, "readAlerts", Qt::QueuedConnection);
|
||||||
@ -490,7 +507,7 @@ Session::Session(QObject *parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// initialize PortForwarder instance
|
// initialize PortForwarder instance
|
||||||
Net::PortForwarder::initInstance(m_nativeSession);
|
new PortForwarderImpl {m_nativeSession};
|
||||||
|
|
||||||
initMetrics();
|
initMetrics();
|
||||||
m_statsUpdateTimer.start();
|
m_statsUpdateTimer.start();
|
||||||
@ -936,7 +953,7 @@ Session::~Session()
|
|||||||
|
|
||||||
// We must delete PortForwarderImpl before
|
// We must delete PortForwarderImpl before
|
||||||
// we delete libtorrent::session
|
// we delete libtorrent::session
|
||||||
Net::PortForwarder::freeInstance();
|
delete Net::PortForwarder::instance();
|
||||||
|
|
||||||
qDebug("Deleting the session");
|
qDebug("Deleting the session");
|
||||||
delete m_nativeSession;
|
delete m_nativeSession;
|
||||||
@ -1665,7 +1682,7 @@ bool Session::cancelLoadMetadata(const InfoHash &hash)
|
|||||||
const libt::torrent_handle torrent = m_nativeSession->find_torrent(hash);
|
const libt::torrent_handle torrent = m_nativeSession->find_torrent(hash);
|
||||||
if (!torrent.is_valid()) return false;
|
if (!torrent.is_valid()) return false;
|
||||||
|
|
||||||
if (!torrent.status(0).has_metadata) {
|
if (!torrent.status(LTStatusFlags {0}).has_metadata) {
|
||||||
// if hidden torrent is still loading metadata...
|
// if hidden torrent is still loading metadata...
|
||||||
--m_extraLimit;
|
--m_extraLimit;
|
||||||
adjustLimits();
|
adjustLimits();
|
||||||
@ -1930,11 +1947,21 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne
|
|||||||
if (!fromMagnetUri) {
|
if (!fromMagnetUri) {
|
||||||
if (params.restored) {
|
if (params.restored) {
|
||||||
// Set torrent fast resume data
|
// Set torrent fast resume data
|
||||||
p.resume_data = {fastresumeData.constData(), fastresumeData.constData() + fastresumeData.size()};
|
p.resume_data = std::vector<char> {fastresumeData.constData(), fastresumeData.constData() + fastresumeData.size()};
|
||||||
p.flags |= libt::add_torrent_params::flag_use_resume_save_path;
|
p.flags |= libt::add_torrent_params::flag_use_resume_save_path;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p.file_priorities = {params.filePriorities.begin(), params.filePriorities.end()};
|
Q_ASSERT(p.file_priorities.empty());
|
||||||
|
std::transform(params.filePriorities.cbegin(), params.filePriorities.cend()
|
||||||
|
, std::back_inserter(p.file_priorities), [](DownloadPriority priority)
|
||||||
|
{
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
return static_cast<boost::uint8_t>(priority);
|
||||||
|
#else
|
||||||
|
return static_cast<lt::download_priority_t>(
|
||||||
|
static_cast<lt::download_priority_t::underlying_type>(priority));
|
||||||
|
#endif
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3966,7 +3993,11 @@ void Session::handlePortmapAlert(const libt::portmap_alert *p)
|
|||||||
void Session::handlePeerBlockedAlert(const libt::peer_blocked_alert *p)
|
void Session::handlePeerBlockedAlert(const libt::peer_blocked_alert *p)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
#if LIBTORRENT_VERSION_NUM < 10200
|
||||||
const std::string ip = p->ip.to_string(ec);
|
const std::string ip = p->ip.to_string(ec);
|
||||||
|
#else
|
||||||
|
const std::string ip = p->endpoint.address().to_string(ec);
|
||||||
|
#endif
|
||||||
QString reason;
|
QString reason;
|
||||||
switch (p->reason) {
|
switch (p->reason) {
|
||||||
case libt::peer_blocked_alert::ip_filter:
|
case libt::peer_blocked_alert::ip_filter:
|
||||||
@ -4182,31 +4213,31 @@ namespace
|
|||||||
if (ec || (fast.type() != libt::bdecode_node::dict_t)) return false;
|
if (ec || (fast.type() != libt::bdecode_node::dict_t)) return false;
|
||||||
|
|
||||||
torrentParams.savePath = Profile::instance().fromPortablePath(
|
torrentParams.savePath = Profile::instance().fromPortablePath(
|
||||||
Utils::Fs::fromNativePath(QString::fromStdString(fast.dict_find_string_value("qBt-savePath"))));
|
Utils::Fs::fromNativePath(fromLTString(fast.dict_find_string_value("qBt-savePath"))));
|
||||||
|
|
||||||
std::string ratioLimitString = fast.dict_find_string_value("qBt-ratioLimit");
|
LTString ratioLimitString = fast.dict_find_string_value("qBt-ratioLimit");
|
||||||
if (ratioLimitString.empty())
|
if (ratioLimitString.empty())
|
||||||
torrentParams.ratioLimit = fast.dict_find_int_value("qBt-ratioLimit", TorrentHandle::USE_GLOBAL_RATIO * 1000) / 1000.0;
|
torrentParams.ratioLimit = fast.dict_find_int_value("qBt-ratioLimit", TorrentHandle::USE_GLOBAL_RATIO * 1000) / 1000.0;
|
||||||
else
|
else
|
||||||
torrentParams.ratioLimit = QString::fromStdString(ratioLimitString).toDouble();
|
torrentParams.ratioLimit = fromLTString(ratioLimitString).toDouble();
|
||||||
torrentParams.seedingTimeLimit = fast.dict_find_int_value("qBt-seedingTimeLimit", TorrentHandle::USE_GLOBAL_SEEDING_TIME);
|
torrentParams.seedingTimeLimit = fast.dict_find_int_value("qBt-seedingTimeLimit", TorrentHandle::USE_GLOBAL_SEEDING_TIME);
|
||||||
// **************************************************************************************
|
// **************************************************************************************
|
||||||
// Workaround to convert legacy label to category
|
// Workaround to convert legacy label to category
|
||||||
// TODO: Should be removed in future
|
// TODO: Should be removed in future
|
||||||
torrentParams.category = QString::fromStdString(fast.dict_find_string_value("qBt-label"));
|
torrentParams.category = fromLTString(fast.dict_find_string_value("qBt-label"));
|
||||||
if (torrentParams.category.isEmpty())
|
if (torrentParams.category.isEmpty())
|
||||||
// **************************************************************************************
|
// **************************************************************************************
|
||||||
torrentParams.category = QString::fromStdString(fast.dict_find_string_value("qBt-category"));
|
torrentParams.category = fromLTString(fast.dict_find_string_value("qBt-category"));
|
||||||
// auto because the return type depends on the #if above.
|
// auto because the return type depends on the #if above.
|
||||||
const auto tagsEntry = fast.dict_find_list("qBt-tags");
|
const auto tagsEntry = fast.dict_find_list("qBt-tags");
|
||||||
if (isList(tagsEntry))
|
if (isList(tagsEntry))
|
||||||
torrentParams.tags = entryListToSet(tagsEntry);
|
torrentParams.tags = entryListToSet(tagsEntry);
|
||||||
torrentParams.name = QString::fromStdString(fast.dict_find_string_value("qBt-name"));
|
torrentParams.name = fromLTString(fast.dict_find_string_value("qBt-name"));
|
||||||
torrentParams.hasSeedStatus = fast.dict_find_int_value("qBt-seedStatus");
|
torrentParams.hasSeedStatus = fast.dict_find_int_value("qBt-seedStatus");
|
||||||
torrentParams.disableTempPath = fast.dict_find_int_value("qBt-tempPathDisabled");
|
torrentParams.disableTempPath = fast.dict_find_int_value("qBt-tempPathDisabled");
|
||||||
torrentParams.hasRootFolder = fast.dict_find_int_value("qBt-hasRootFolder");
|
torrentParams.hasRootFolder = fast.dict_find_int_value("qBt-hasRootFolder");
|
||||||
|
|
||||||
magnetUri = MagnetUri(QString::fromStdString(fast.dict_find_string_value("qBt-magnetUri")));
|
magnetUri = MagnetUri(fromLTString(fast.dict_find_string_value("qBt-magnetUri")));
|
||||||
const bool isAutoManaged = fast.dict_find_int_value("auto_managed");
|
const bool isAutoManaged = fast.dict_find_int_value("auto_managed");
|
||||||
const bool isPaused = fast.dict_find_int_value("paused");
|
const bool isPaused = fast.dict_find_int_value("paused");
|
||||||
torrentParams.paused = fast.dict_find_int_value("qBt-paused", (isPaused && !isAutoManaged));
|
torrentParams.paused = fast.dict_find_int_value("qBt-paused", (isPaused && !isAutoManaged));
|
||||||
|
@ -47,54 +47,12 @@
|
|||||||
#include "base/settingvalue.h"
|
#include "base/settingvalue.h"
|
||||||
#include "base/tristatebool.h"
|
#include "base/tristatebool.h"
|
||||||
#include "base/types.h"
|
#include "base/types.h"
|
||||||
|
#include "private/libtorrentfwd.h"
|
||||||
#include "addtorrentparams.h"
|
#include "addtorrentparams.h"
|
||||||
#include "cachestatus.h"
|
#include "cachestatus.h"
|
||||||
#include "sessionstatus.h"
|
#include "sessionstatus.h"
|
||||||
#include "torrentinfo.h"
|
#include "torrentinfo.h"
|
||||||
|
|
||||||
namespace libtorrent
|
|
||||||
{
|
|
||||||
class session;
|
|
||||||
struct torrent_handle;
|
|
||||||
class entry;
|
|
||||||
struct ip_filter;
|
|
||||||
struct settings_pack;
|
|
||||||
|
|
||||||
class alert;
|
|
||||||
struct torrent_alert;
|
|
||||||
struct state_update_alert;
|
|
||||||
struct stats_alert;
|
|
||||||
struct add_torrent_alert;
|
|
||||||
struct torrent_checked_alert;
|
|
||||||
struct torrent_finished_alert;
|
|
||||||
struct torrent_removed_alert;
|
|
||||||
struct torrent_deleted_alert;
|
|
||||||
struct torrent_delete_failed_alert;
|
|
||||||
struct torrent_paused_alert;
|
|
||||||
struct torrent_resumed_alert;
|
|
||||||
struct save_resume_data_alert;
|
|
||||||
struct save_resume_data_failed_alert;
|
|
||||||
struct file_renamed_alert;
|
|
||||||
struct storage_moved_alert;
|
|
||||||
struct storage_moved_failed_alert;
|
|
||||||
struct metadata_received_alert;
|
|
||||||
struct file_error_alert;
|
|
||||||
struct file_completed_alert;
|
|
||||||
struct tracker_error_alert;
|
|
||||||
struct tracker_reply_alert;
|
|
||||||
struct tracker_warning_alert;
|
|
||||||
struct portmap_error_alert;
|
|
||||||
struct portmap_alert;
|
|
||||||
struct peer_blocked_alert;
|
|
||||||
struct peer_ban_alert;
|
|
||||||
struct fastresume_rejected_alert;
|
|
||||||
struct url_seed_alert;
|
|
||||||
struct listen_succeeded_alert;
|
|
||||||
struct listen_failed_alert;
|
|
||||||
struct external_ip_alert;
|
|
||||||
struct session_stats_alert;
|
|
||||||
}
|
|
||||||
|
|
||||||
class QThread;
|
class QThread;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
class QStringList;
|
class QStringList;
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <libtorrent/create_torrent.hpp>
|
#include <libtorrent/create_torrent.hpp>
|
||||||
#include <libtorrent/storage.hpp>
|
#include <libtorrent/storage.hpp>
|
||||||
#include <libtorrent/torrent_info.hpp>
|
#include <libtorrent/torrent_info.hpp>
|
||||||
|
#include <libtorrent/version.hpp>
|
||||||
|
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
@ -47,6 +48,12 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
using CreateFlags = int;
|
||||||
|
#else
|
||||||
|
using CreateFlags = lt::create_flags_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
// do not include files and folders whose
|
// do not include files and folders whose
|
||||||
// name starts with a .
|
// name starts with a .
|
||||||
bool fileFilter(const std::string &f)
|
bool fileFilter(const std::string &f)
|
||||||
@ -131,7 +138,7 @@ void TorrentCreatorThread::run()
|
|||||||
if (isInterruptionRequested()) return;
|
if (isInterruptionRequested()) return;
|
||||||
|
|
||||||
libt::create_torrent newTorrent(fs, m_params.pieceSize, -1
|
libt::create_torrent newTorrent(fs, m_params.pieceSize, -1
|
||||||
, (m_params.isAlignmentOptimized ? libt::create_torrent::optimize_alignment : 0));
|
, (m_params.isAlignmentOptimized ? libt::create_torrent::optimize_alignment : CreateFlags {}));
|
||||||
|
|
||||||
// Add url seeds
|
// Add url seeds
|
||||||
for (QString seed : asConst(m_params.urlSeeds)) {
|
for (QString seed : asConst(m_params.urlSeeds)) {
|
||||||
@ -203,5 +210,5 @@ int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const i
|
|||||||
libt::add_files(fs, Utils::Fs::toNativePath(inputPath).toStdString(), fileFilter);
|
libt::add_files(fs, Utils::Fs::toNativePath(inputPath).toStdString(), fileFilter);
|
||||||
|
|
||||||
return libt::create_torrent(fs, pieceSize, -1
|
return libt::create_torrent(fs, pieceSize, -1
|
||||||
, (isAlignmentOptimized ? libt::create_torrent::optimize_alignment : 0)).num_pieces();
|
, (isAlignmentOptimized ? libt::create_torrent::optimize_alignment : CreateFlags {})).num_pieces();
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include <libtorrent/entry.hpp>
|
#include <libtorrent/entry.hpp>
|
||||||
#include <libtorrent/magnet_uri.hpp>
|
#include <libtorrent/magnet_uri.hpp>
|
||||||
#include <libtorrent/time.hpp>
|
#include <libtorrent/time.hpp>
|
||||||
|
#include <libtorrent/version.hpp>
|
||||||
|
|
||||||
#include <QBitArray>
|
#include <QBitArray>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
@ -69,6 +70,28 @@ using namespace BitTorrent;
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
using LTDownloadPriority = int;
|
||||||
|
using LTDownloadPriorityUnderlyingType = int;
|
||||||
|
using LTQueuePosition = int;
|
||||||
|
#else
|
||||||
|
using LTDownloadPriority = lt::download_priority_t;
|
||||||
|
using LTDownloadPriorityUnderlyingType = lt::download_priority_t::underlying_type;
|
||||||
|
using LTQueuePosition = lt::queue_position_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::vector<LTDownloadPriority> toLTDownloadPriorities(const QVector<DownloadPriority> &priorities)
|
||||||
|
{
|
||||||
|
std::vector<LTDownloadPriority> out;
|
||||||
|
std::transform(priorities.cbegin(), priorities.cend()
|
||||||
|
, std::back_inserter(out), [](BitTorrent::DownloadPriority priority)
|
||||||
|
{
|
||||||
|
return static_cast<LTDownloadPriority>(
|
||||||
|
static_cast<LTDownloadPriorityUnderlyingType>(priority));
|
||||||
|
});
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
using ListType = libt::entry::list_type;
|
using ListType = libt::entry::list_type;
|
||||||
|
|
||||||
ListType setToEntryList(const QSet<QString> &input)
|
ListType setToEntryList(const QSet<QString> &input)
|
||||||
@ -635,11 +658,21 @@ QStringList TorrentHandle::absoluteFilePathsUnwanted() const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<int> TorrentHandle::filePriorities() const
|
QVector<DownloadPriority> TorrentHandle::filePriorities() const
|
||||||
{
|
{
|
||||||
const std::vector<int> fp = m_nativeHandle.file_priorities();
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
const std::vector<LTDownloadPriority> fp = m_nativeHandle.file_priorities();
|
||||||
|
#else
|
||||||
|
const std::vector<LTDownloadPriority> fp = m_nativeHandle.get_file_priorities();
|
||||||
|
#endif
|
||||||
|
|
||||||
return QVector<int>::fromStdVector(fp);
|
QVector<DownloadPriority> ret;
|
||||||
|
std::transform(fp.cbegin(), fp.cend(), std::back_inserter(ret), [](LTDownloadPriority priority)
|
||||||
|
{
|
||||||
|
return static_cast<DownloadPriority>(
|
||||||
|
static_cast<std::underlying_type<DownloadPriority>::type>(priority));
|
||||||
|
});
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
TorrentInfo TorrentHandle::info() const
|
TorrentInfo TorrentHandle::info() const
|
||||||
@ -838,18 +871,22 @@ bool TorrentHandle::hasError() const
|
|||||||
|
|
||||||
bool TorrentHandle::hasFilteredPieces() const
|
bool TorrentHandle::hasFilteredPieces() const
|
||||||
{
|
{
|
||||||
const std::vector<int> pp = m_nativeHandle.piece_priorities();
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
return std::any_of(pp.cbegin(), pp.cend(), [](const int priority)
|
const std::vector<LTDownloadPriority> pp = m_nativeHandle.piece_priorities();
|
||||||
|
#else
|
||||||
|
const std::vector<LTDownloadPriority> pp = m_nativeHandle.get_piece_priorities();
|
||||||
|
#endif
|
||||||
|
return std::any_of(pp.cbegin(), pp.cend(), [](const LTDownloadPriority priority)
|
||||||
{
|
{
|
||||||
return (priority == 0);
|
return (priority == LTDownloadPriority {0});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
int TorrentHandle::queuePosition() const
|
int TorrentHandle::queuePosition() const
|
||||||
{
|
{
|
||||||
if (m_nativeStatus.queue_position < 0) return 0;
|
if (m_nativeStatus.queue_position < LTQueuePosition {0}) return 0;
|
||||||
|
|
||||||
return m_nativeStatus.queue_position + 1;
|
return static_cast<int>(m_nativeStatus.queue_position) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TorrentHandle::error() const
|
QString TorrentHandle::error() const
|
||||||
@ -1244,7 +1281,7 @@ void TorrentHandle::setFirstLastPiecePriority(const bool enabled)
|
|||||||
setFirstLastPiecePriorityImpl(enabled);
|
setFirstLastPiecePriorityImpl(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentHandle::setFirstLastPiecePriorityImpl(const bool enabled, const QVector<int> &updatedFilePrio)
|
void TorrentHandle::setFirstLastPiecePriorityImpl(const bool enabled, const QVector<DownloadPriority> &updatedFilePrio)
|
||||||
{
|
{
|
||||||
// Download first and last pieces first for every file in the torrent
|
// Download first and last pieces first for every file in the torrent
|
||||||
|
|
||||||
@ -1253,17 +1290,24 @@ void TorrentHandle::setFirstLastPiecePriorityImpl(const bool enabled, const QVec
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
const std::vector<LTDownloadPriority> filePriorities = !updatedFilePrio.isEmpty() ? toLTDownloadPriorities(updatedFilePrio)
|
||||||
|
: nativeHandle().file_priorities();
|
||||||
|
std::vector<LTDownloadPriority> piecePriorities = nativeHandle().piece_priorities();
|
||||||
|
#else
|
||||||
|
const std::vector<LTDownloadPriority> filePriorities = !updatedFilePrio.isEmpty() ? toLTDownloadPriorities(updatedFilePrio)
|
||||||
|
: nativeHandle().get_file_priorities();
|
||||||
|
std::vector<LTDownloadPriority> piecePriorities = nativeHandle().get_piece_priorities();
|
||||||
|
#endif
|
||||||
// Updating file priorities is an async operation in libtorrent, when we just updated it and immediately query it
|
// Updating file priorities is an async operation in libtorrent, when we just updated it and immediately query it
|
||||||
// we might get the old/wrong values, so we rely on `updatedFilePrio` in this case.
|
// we might get the old/wrong values, so we rely on `updatedFilePrio` in this case.
|
||||||
const std::vector<int> filePriorities = !updatedFilePrio.isEmpty() ? updatedFilePrio.toStdVector() : nativeHandle().file_priorities();
|
|
||||||
std::vector<int> piecePriorities = nativeHandle().piece_priorities();
|
|
||||||
for (int index = 0; index < static_cast<int>(filePriorities.size()); ++index) {
|
for (int index = 0; index < static_cast<int>(filePriorities.size()); ++index) {
|
||||||
const int filePrio = filePriorities[index];
|
const LTDownloadPriority filePrio = filePriorities[index];
|
||||||
if (filePrio <= 0)
|
if (filePrio <= LTDownloadPriority {0})
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Determine the priority to set
|
// Determine the priority to set
|
||||||
const int newPrio = enabled ? 7 : filePrio;
|
const int newPrio = enabled ? LTDownloadPriority {7} : filePrio;
|
||||||
const TorrentInfo::PieceRange extremities = info().filePieces(index);
|
const TorrentInfo::PieceRange extremities = info().filePieces(index);
|
||||||
|
|
||||||
// worst case: AVI index = 1% of total file size (at the end of the file)
|
// worst case: AVI index = 1% of total file size (at the end of the file)
|
||||||
@ -1349,8 +1393,11 @@ void TorrentHandle::renameFile(int index, const QString &name)
|
|||||||
bool TorrentHandle::saveTorrentFile(const QString &path)
|
bool TorrentHandle::saveTorrentFile(const QString &path)
|
||||||
{
|
{
|
||||||
if (!m_torrentInfo.isValid()) return false;
|
if (!m_torrentInfo.isValid()) return false;
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
const libt::create_torrent torrentCreator = libt::create_torrent(*(m_torrentInfo.nativeInfo()), true);
|
const libt::create_torrent torrentCreator = libt::create_torrent(*(m_torrentInfo.nativeInfo()), true);
|
||||||
|
#else
|
||||||
|
const libt::create_torrent torrentCreator = libt::create_torrent(*(m_torrentInfo.nativeInfo()));
|
||||||
|
#endif
|
||||||
const libt::entry torrentEntry = torrentCreator.generate();
|
const libt::entry torrentEntry = torrentCreator.generate();
|
||||||
|
|
||||||
QVector<char> out;
|
QVector<char> out;
|
||||||
@ -1572,7 +1619,7 @@ void TorrentHandle::handleSaveResumeDataAlert(const libtorrent::save_resume_data
|
|||||||
resumeData["qBt-name"] = m_name.toStdString();
|
resumeData["qBt-name"] = m_name.toStdString();
|
||||||
resumeData["qBt-seedStatus"] = m_hasSeedStatus;
|
resumeData["qBt-seedStatus"] = m_hasSeedStatus;
|
||||||
resumeData["qBt-tempPathDisabled"] = m_tempPathDisabled;
|
resumeData["qBt-tempPathDisabled"] = m_tempPathDisabled;
|
||||||
resumeData["qBt-queuePosition"] = (nativeHandle().queue_position() + 1); // qBt starts queue at 1
|
resumeData["qBt-queuePosition"] = (static_cast<int>(nativeHandle().queue_position()) + 1); // qBt starts queue at 1
|
||||||
resumeData["qBt-hasRootFolder"] = m_hasRootFolder;
|
resumeData["qBt-hasRootFolder"] = m_hasRootFolder;
|
||||||
|
|
||||||
m_session->handleTorrentResumeDataReady(this, resumeData);
|
m_session->handleTorrentResumeDataReady(this, resumeData);
|
||||||
@ -1916,7 +1963,7 @@ QString TorrentHandle::toMagnetUri() const
|
|||||||
return QString::fromStdString(libt::make_magnet_uri(m_nativeHandle));
|
return QString::fromStdString(libt::make_magnet_uri(m_nativeHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentHandle::prioritizeFiles(const QVector<int> &priorities)
|
void TorrentHandle::prioritizeFiles(const QVector<DownloadPriority> &priorities)
|
||||||
{
|
{
|
||||||
if (!hasMetadata()) return;
|
if (!hasMetadata()) return;
|
||||||
if (priorities.size() != filesCount()) return;
|
if (priorities.size() != filesCount()) return;
|
||||||
@ -1927,23 +1974,25 @@ void TorrentHandle::prioritizeFiles(const QVector<int> &priorities)
|
|||||||
// Reset 'm_hasSeedStatus' if needed in order to react again to
|
// Reset 'm_hasSeedStatus' if needed in order to react again to
|
||||||
// 'torrent_finished_alert' and eg show tray notifications
|
// 'torrent_finished_alert' and eg show tray notifications
|
||||||
const QVector<qreal> progress = filesProgress();
|
const QVector<qreal> progress = filesProgress();
|
||||||
const QVector<int> oldPriorities = filePriorities();
|
const QVector<DownloadPriority> oldPriorities = filePriorities();
|
||||||
for (int i = 0; i < oldPriorities.size(); ++i) {
|
for (int i = 0; i < oldPriorities.size(); ++i) {
|
||||||
if ((oldPriorities[i] == 0) && (priorities[i] > 0) && (progress[i] < 1.0)) {
|
if ((oldPriorities[i] == DownloadPriority::Ignored)
|
||||||
|
&& (priorities[i] > DownloadPriority::Ignored)
|
||||||
|
&& (progress[i] < 1.0)) {
|
||||||
m_hasSeedStatus = false;
|
m_hasSeedStatus = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << Q_FUNC_INFO << "Changing files priorities...";
|
qDebug() << Q_FUNC_INFO << "Changing files priorities...";
|
||||||
m_nativeHandle.prioritize_files(priorities.toStdVector());
|
m_nativeHandle.prioritize_files(toLTDownloadPriorities(priorities));
|
||||||
|
|
||||||
qDebug() << Q_FUNC_INFO << "Moving unwanted files to .unwanted folder and conversely...";
|
qDebug() << Q_FUNC_INFO << "Moving unwanted files to .unwanted folder and conversely...";
|
||||||
const QString spath = savePath(true);
|
const QString spath = savePath(true);
|
||||||
for (int i = 0; i < priorities.size(); ++i) {
|
for (int i = 0; i < priorities.size(); ++i) {
|
||||||
const QString filepath = filePath(i);
|
const QString filepath = filePath(i);
|
||||||
// Move unwanted files to a .unwanted subfolder
|
// Move unwanted files to a .unwanted subfolder
|
||||||
if (priorities[i] == 0) {
|
if (priorities[i] == DownloadPriority::Ignored) {
|
||||||
const QString oldAbsPath = QDir(spath).absoluteFilePath(filepath);
|
const QString oldAbsPath = QDir(spath).absoluteFilePath(filepath);
|
||||||
const QString parentAbsPath = Utils::Fs::branchPath(oldAbsPath);
|
const QString parentAbsPath = Utils::Fs::branchPath(oldAbsPath);
|
||||||
// Make sure the file does not already exists
|
// Make sure the file does not already exists
|
||||||
@ -1976,7 +2025,7 @@ void TorrentHandle::prioritizeFiles(const QVector<int> &priorities)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Move wanted files back to their original folder
|
// Move wanted files back to their original folder
|
||||||
if (priorities[i] > 0) {
|
if (priorities[i] > DownloadPriority::Ignored) {
|
||||||
const QString parentRelPath = Utils::Fs::branchPath(filepath);
|
const QString parentRelPath = Utils::Fs::branchPath(filepath);
|
||||||
if (QDir(parentRelPath).dirName() == ".unwanted") {
|
if (QDir(parentRelPath).dirName() == ".unwanted") {
|
||||||
const QString oldName = Utils::Fs::fileName(filepath);
|
const QString oldName = Utils::Fs::fileName(filepath);
|
||||||
|
@ -42,7 +42,9 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
|
#include "private/libtorrentfwd.h"
|
||||||
#include "private/speedmonitor.h"
|
#include "private/speedmonitor.h"
|
||||||
|
#include "downloadpriority.h"
|
||||||
#include "infohash.h"
|
#include "infohash.h"
|
||||||
#include "torrentinfo.h"
|
#include "torrentinfo.h"
|
||||||
|
|
||||||
@ -53,29 +55,6 @@ class QDateTime;
|
|||||||
class QStringList;
|
class QStringList;
|
||||||
class QUrl;
|
class QUrl;
|
||||||
|
|
||||||
namespace libtorrent
|
|
||||||
{
|
|
||||||
class alert;
|
|
||||||
struct fastresume_rejected_alert;
|
|
||||||
struct file_completed_alert;
|
|
||||||
struct file_renamed_alert;
|
|
||||||
struct file_rename_failed_alert;
|
|
||||||
struct metadata_received_alert;
|
|
||||||
struct save_resume_data_alert;
|
|
||||||
struct save_resume_data_failed_alert;
|
|
||||||
struct stats_alert;
|
|
||||||
struct storage_moved_alert;
|
|
||||||
struct storage_moved_failed_alert;
|
|
||||||
struct torrent_checked_alert;
|
|
||||||
struct torrent_finished_alert;
|
|
||||||
struct torrent_paused_alert;
|
|
||||||
struct torrent_resumed_alert;
|
|
||||||
struct torrent_status;
|
|
||||||
struct tracker_error_alert;
|
|
||||||
struct tracker_reply_alert;
|
|
||||||
struct tracker_warning_alert;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace BitTorrent
|
namespace BitTorrent
|
||||||
{
|
{
|
||||||
class PeerInfo;
|
class PeerInfo;
|
||||||
@ -103,7 +82,7 @@ namespace BitTorrent
|
|||||||
int uploadLimit;
|
int uploadLimit;
|
||||||
int downloadLimit;
|
int downloadLimit;
|
||||||
// for new torrents
|
// for new torrents
|
||||||
QVector<int> filePriorities;
|
QVector<DownloadPriority> filePriorities;
|
||||||
// for restored torrents
|
// for restored torrents
|
||||||
qreal ratioLimit;
|
qreal ratioLimit;
|
||||||
int seedingTimeLimit;
|
int seedingTimeLimit;
|
||||||
@ -258,7 +237,7 @@ namespace BitTorrent
|
|||||||
qlonglong fileSize(int index) const;
|
qlonglong fileSize(int index) const;
|
||||||
QStringList absoluteFilePaths() const;
|
QStringList absoluteFilePaths() const;
|
||||||
QStringList absoluteFilePathsUnwanted() const;
|
QStringList absoluteFilePathsUnwanted() const;
|
||||||
QVector<int> filePriorities() const;
|
QVector<DownloadPriority> filePriorities() const;
|
||||||
|
|
||||||
TorrentInfo info() const;
|
TorrentInfo info() const;
|
||||||
bool isSeed() const;
|
bool isSeed() const;
|
||||||
@ -337,7 +316,7 @@ namespace BitTorrent
|
|||||||
void forceRecheck();
|
void forceRecheck();
|
||||||
void renameFile(int index, const QString &name);
|
void renameFile(int index, const QString &name);
|
||||||
bool saveTorrentFile(const QString &path);
|
bool saveTorrentFile(const QString &path);
|
||||||
void prioritizeFiles(const QVector<int> &priorities);
|
void prioritizeFiles(const QVector<DownloadPriority> &priorities);
|
||||||
void setRatioLimit(qreal limit);
|
void setRatioLimit(qreal limit);
|
||||||
void setSeedingTimeLimit(int limit);
|
void setSeedingTimeLimit(int limit);
|
||||||
void setUploadLimit(int limit);
|
void setUploadLimit(int limit);
|
||||||
@ -410,7 +389,7 @@ namespace BitTorrent
|
|||||||
bool addTracker(const TrackerEntry &tracker);
|
bool addTracker(const TrackerEntry &tracker);
|
||||||
bool addUrlSeed(const QUrl &urlSeed);
|
bool addUrlSeed(const QUrl &urlSeed);
|
||||||
bool removeUrlSeed(const QUrl &urlSeed);
|
bool removeUrlSeed(const QUrl &urlSeed);
|
||||||
void setFirstLastPiecePriorityImpl(bool enabled, const QVector<int> &updatedFilePrio = {});
|
void setFirstLastPiecePriorityImpl(bool enabled, const QVector<DownloadPriority> &updatedFilePrio = {});
|
||||||
|
|
||||||
Session *const m_session;
|
Session *const m_session;
|
||||||
libtorrent::torrent_handle m_nativeHandle;
|
libtorrent::torrent_handle m_nativeHandle;
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include "torrentinfo.h"
|
#include "torrentinfo.h"
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
#include <libtorrent/error_code.hpp>
|
#include <libtorrent/error_code.hpp>
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
@ -42,12 +43,27 @@
|
|||||||
#include "infohash.h"
|
#include "infohash.h"
|
||||||
#include "trackerentry.h"
|
#include "trackerentry.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
using LTPieceIndex = int;
|
||||||
|
using LTFileIndex = int;
|
||||||
|
#else
|
||||||
|
using LTPieceIndex = lt::piece_index_t;
|
||||||
|
using LTFileIndex = lt::file_index_t;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
namespace libt = libtorrent;
|
namespace libt = libtorrent;
|
||||||
using namespace BitTorrent;
|
using namespace BitTorrent;
|
||||||
|
|
||||||
TorrentInfo::TorrentInfo(NativeConstPtr nativeInfo)
|
TorrentInfo::TorrentInfo(NativeConstPtr nativeInfo)
|
||||||
{
|
{
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
m_nativeInfo = boost::const_pointer_cast<libt::torrent_info>(nativeInfo);
|
m_nativeInfo = boost::const_pointer_cast<libt::torrent_info>(nativeInfo);
|
||||||
|
#else
|
||||||
|
m_nativeInfo = std::const_pointer_cast<libt::torrent_info>(nativeInfo);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TorrentInfo::TorrentInfo(const TorrentInfo &other)
|
TorrentInfo::TorrentInfo(const TorrentInfo &other)
|
||||||
@ -190,7 +206,7 @@ int TorrentInfo::pieceLength() const
|
|||||||
int TorrentInfo::pieceLength(const int index) const
|
int TorrentInfo::pieceLength(const int index) const
|
||||||
{
|
{
|
||||||
if (!isValid()) return -1;
|
if (!isValid()) return -1;
|
||||||
return m_nativeInfo->piece_size(index);
|
return m_nativeInfo->piece_size(LTPieceIndex {index});
|
||||||
}
|
}
|
||||||
|
|
||||||
int TorrentInfo::piecesCount() const
|
int TorrentInfo::piecesCount() const
|
||||||
@ -202,7 +218,8 @@ int TorrentInfo::piecesCount() const
|
|||||||
QString TorrentInfo::filePath(const int index) const
|
QString TorrentInfo::filePath(const int index) const
|
||||||
{
|
{
|
||||||
if (!isValid()) return {};
|
if (!isValid()) return {};
|
||||||
return Utils::Fs::fromNativePath(QString::fromStdString(m_nativeInfo->files().file_path(index)));
|
return Utils::Fs::fromNativePath(
|
||||||
|
QString::fromStdString(m_nativeInfo->files().file_path(LTFileIndex {index})));
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList TorrentInfo::filePaths() const
|
QStringList TorrentInfo::filePaths() const
|
||||||
@ -222,19 +239,20 @@ QString TorrentInfo::fileName(const int index) const
|
|||||||
QString TorrentInfo::origFilePath(const int index) const
|
QString TorrentInfo::origFilePath(const int index) const
|
||||||
{
|
{
|
||||||
if (!isValid()) return {};
|
if (!isValid()) return {};
|
||||||
return Utils::Fs::fromNativePath(QString::fromStdString(m_nativeInfo->orig_files().file_path(index)));
|
return Utils::Fs::fromNativePath(
|
||||||
|
QString::fromStdString(m_nativeInfo->orig_files().file_path(LTFileIndex {index})));
|
||||||
}
|
}
|
||||||
|
|
||||||
qlonglong TorrentInfo::fileSize(const int index) const
|
qlonglong TorrentInfo::fileSize(const int index) const
|
||||||
{
|
{
|
||||||
if (!isValid()) return -1;
|
if (!isValid()) return -1;
|
||||||
return m_nativeInfo->files().file_size(index);
|
return m_nativeInfo->files().file_size(LTFileIndex {index});
|
||||||
}
|
}
|
||||||
|
|
||||||
qlonglong TorrentInfo::fileOffset(const int index) const
|
qlonglong TorrentInfo::fileOffset(const int index) const
|
||||||
{
|
{
|
||||||
if (!isValid()) return -1;
|
if (!isValid()) return -1;
|
||||||
return m_nativeInfo->files().file_offset(index);
|
return m_nativeInfo->files().file_offset(LTFileIndex {index});
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<TrackerEntry> TorrentInfo::trackers() const
|
QList<TrackerEntry> TorrentInfo::trackers() const
|
||||||
@ -285,11 +303,12 @@ QVector<int> TorrentInfo::fileIndicesForPiece(const int pieceIndex) const
|
|||||||
return {};
|
return {};
|
||||||
|
|
||||||
const std::vector<libt::file_slice> files(
|
const std::vector<libt::file_slice> files(
|
||||||
nativeInfo()->map_block(pieceIndex, 0, nativeInfo()->piece_size(pieceIndex)));
|
nativeInfo()->map_block(LTPieceIndex {pieceIndex}, 0
|
||||||
|
, nativeInfo()->piece_size(LTPieceIndex {pieceIndex})));
|
||||||
QVector<int> res;
|
QVector<int> res;
|
||||||
res.reserve(int(files.size()));
|
res.reserve(int(files.size()));
|
||||||
std::transform(files.begin(), files.end(), std::back_inserter(res),
|
std::transform(files.begin(), files.end(), std::back_inserter(res),
|
||||||
[](const libt::file_slice &s) { return s.file_index; });
|
[](const libt::file_slice &s) { return static_cast<int>(s.file_index); });
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -304,7 +323,7 @@ QVector<QByteArray> TorrentInfo::pieceHashes() const
|
|||||||
hashes.reserve(count);
|
hashes.reserve(count);
|
||||||
|
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
hashes += { m_nativeInfo->hash_for_piece_ptr(i), libtorrent::sha1_hash::size };
|
hashes += {m_nativeInfo->hash_for_piece_ptr(LTPieceIndex {i}), InfoHash::length()};
|
||||||
|
|
||||||
return hashes;
|
return hashes;
|
||||||
}
|
}
|
||||||
@ -333,8 +352,8 @@ TorrentInfo::PieceRange TorrentInfo::filePieces(const int fileIndex) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
const libt::file_storage &files = nativeInfo()->files();
|
const libt::file_storage &files = nativeInfo()->files();
|
||||||
const auto fileSize = files.file_size(fileIndex);
|
const auto fileSize = files.file_size(LTFileIndex {fileIndex});
|
||||||
const auto fileOffset = files.file_offset(fileIndex);
|
const auto fileOffset = files.file_offset(LTFileIndex {fileIndex});
|
||||||
return makeInterval(static_cast<int>(fileOffset / pieceLength()),
|
return makeInterval(static_cast<int>(fileOffset / pieceLength()),
|
||||||
static_cast<int>((fileOffset + fileSize - 1) / pieceLength()));
|
static_cast<int>((fileOffset + fileSize - 1) / pieceLength()));
|
||||||
}
|
}
|
||||||
|
@ -30,12 +30,14 @@
|
|||||||
#define BITTORRENT_TORRENTINFO_H
|
#define BITTORRENT_TORRENTINFO_H
|
||||||
|
|
||||||
#include <libtorrent/torrent_info.hpp>
|
#include <libtorrent/torrent_info.hpp>
|
||||||
|
#include <libtorrent/version.hpp>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
#include "base/indexrange.h"
|
#include "base/indexrange.h"
|
||||||
|
#include "private/libtorrentfwd.h"
|
||||||
|
|
||||||
class QByteArray;
|
class QByteArray;
|
||||||
class QDateTime;
|
class QDateTime;
|
||||||
@ -53,8 +55,13 @@ namespace BitTorrent
|
|||||||
Q_DECLARE_TR_FUNCTIONS(TorrentInfo)
|
Q_DECLARE_TR_FUNCTIONS(TorrentInfo)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef boost::shared_ptr<const libtorrent::torrent_info> NativeConstPtr;
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
typedef boost::shared_ptr<libtorrent::torrent_info> NativePtr;
|
using NativeConstPtr = boost::shared_ptr<const libtorrent::torrent_info>;
|
||||||
|
using NativePtr = boost::shared_ptr<libtorrent::torrent_info>;
|
||||||
|
#else
|
||||||
|
using NativeConstPtr = std::shared_ptr<const libtorrent::torrent_info>;
|
||||||
|
using NativePtr = std::shared_ptr<libtorrent::torrent_info>;
|
||||||
|
#endif
|
||||||
|
|
||||||
explicit TorrentInfo(NativeConstPtr nativeInfo = {});
|
explicit TorrentInfo(NativeConstPtr nativeInfo = {});
|
||||||
TorrentInfo(const TorrentInfo &other);
|
TorrentInfo(const TorrentInfo &other);
|
||||||
|
@ -28,6 +28,10 @@
|
|||||||
|
|
||||||
#include "trackerentry.h"
|
#include "trackerentry.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <libtorrent/version.hpp>
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
@ -48,6 +52,19 @@ QString TrackerEntry::url() const
|
|||||||
return QString::fromStdString(m_nativeEntry.url);
|
return QString::fromStdString(m_nativeEntry.url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TrackerEntry::isWorking() const
|
||||||
|
{
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
return m_nativeEntry.is_working();
|
||||||
|
#else
|
||||||
|
return std::any_of(m_nativeEntry.endpoints.begin(), m_nativeEntry.endpoints.end()
|
||||||
|
, [](const lt::announce_endpoint &endpoint)
|
||||||
|
{
|
||||||
|
return endpoint.is_working();
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int TrackerEntry::tier() const
|
int TrackerEntry::tier() const
|
||||||
{
|
{
|
||||||
return m_nativeEntry.tier;
|
return m_nativeEntry.tier;
|
||||||
@ -57,7 +74,7 @@ TrackerEntry::Status TrackerEntry::status() const
|
|||||||
{
|
{
|
||||||
// libtorrent::announce_entry::is_working() returns
|
// libtorrent::announce_entry::is_working() returns
|
||||||
// true when the tracker hasn't been tried yet.
|
// true when the tracker hasn't been tried yet.
|
||||||
if (m_nativeEntry.verified && m_nativeEntry.is_working())
|
if (m_nativeEntry.verified && isWorking())
|
||||||
return Working;
|
return Working;
|
||||||
if ((m_nativeEntry.fails == 0) && m_nativeEntry.updating)
|
if ((m_nativeEntry.fails == 0) && m_nativeEntry.updating)
|
||||||
return Updating;
|
return Updating;
|
||||||
@ -72,6 +89,36 @@ void TrackerEntry::setTier(const int value)
|
|||||||
m_nativeEntry.tier = value;
|
m_nativeEntry.tier = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int TrackerEntry::numSeeds() const
|
||||||
|
{
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
return nativeEntry().scrape_complete;
|
||||||
|
#else
|
||||||
|
// FIXME: Handle all possible endpoints.
|
||||||
|
return nativeEntry().endpoints.empty() ? -1 : nativeEntry().endpoints[0].scrape_complete;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int TrackerEntry::numLeeches() const
|
||||||
|
{
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
return nativeEntry().scrape_incomplete;
|
||||||
|
#else
|
||||||
|
// FIXME: Handle all possible endpoints.
|
||||||
|
return nativeEntry().endpoints.empty() ? -1 : nativeEntry().endpoints[0].scrape_incomplete;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int TrackerEntry::numDownloaded() const
|
||||||
|
{
|
||||||
|
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||||
|
return nativeEntry().scrape_downloaded;
|
||||||
|
#else
|
||||||
|
// FIXME: Handle all possible endpoints.
|
||||||
|
return nativeEntry().endpoints.empty() ? -1 : nativeEntry().endpoints[0].scrape_downloaded;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
libtorrent::announce_entry TrackerEntry::nativeEntry() const
|
libtorrent::announce_entry TrackerEntry::nativeEntry() const
|
||||||
{
|
{
|
||||||
return m_nativeEntry;
|
return m_nativeEntry;
|
||||||
|
@ -53,11 +53,16 @@ namespace BitTorrent
|
|||||||
TrackerEntry &operator=(const TrackerEntry &other) = default;
|
TrackerEntry &operator=(const TrackerEntry &other) = default;
|
||||||
|
|
||||||
QString url() const;
|
QString url() const;
|
||||||
|
bool isWorking() const;
|
||||||
Status status() const;
|
Status status() const;
|
||||||
|
|
||||||
int tier() const;
|
int tier() const;
|
||||||
void setTier(int value);
|
void setTier(int value);
|
||||||
|
|
||||||
|
int numSeeds() const;
|
||||||
|
int numLeeches() const;
|
||||||
|
int numDownloaded() const;
|
||||||
|
|
||||||
libtorrent::announce_entry nativeEntry() const;
|
libtorrent::announce_entry nativeEntry() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -28,110 +28,21 @@
|
|||||||
|
|
||||||
#include "portforwarder.h"
|
#include "portforwarder.h"
|
||||||
|
|
||||||
#include <QDebug>
|
Net::PortForwarder::PortForwarder(QObject *parent)
|
||||||
|
: QObject {parent}
|
||||||
#include <libtorrent/session.hpp>
|
|
||||||
|
|
||||||
#include "base/logger.h"
|
|
||||||
#include "base/settingsstorage.h"
|
|
||||||
|
|
||||||
static const QString KEY_ENABLED = QStringLiteral("Network/PortForwardingEnabled");
|
|
||||||
|
|
||||||
namespace libt = libtorrent;
|
|
||||||
using namespace Net;
|
|
||||||
|
|
||||||
PortForwarder::PortForwarder(libtorrent::session *provider, QObject *parent)
|
|
||||||
: QObject(parent)
|
|
||||||
, m_active(false)
|
|
||||||
, m_provider(provider)
|
|
||||||
{
|
{
|
||||||
if (SettingsStorage::instance()->loadValue(KEY_ENABLED, true).toBool())
|
Q_ASSERT(!m_instance);
|
||||||
start();
|
m_instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
PortForwarder::~PortForwarder()
|
Net::PortForwarder::~PortForwarder()
|
||||||
{
|
{
|
||||||
stop();
|
m_instance = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PortForwarder::initInstance(libtorrent::session *const provider)
|
Net::PortForwarder *Net::PortForwarder::instance()
|
||||||
{
|
|
||||||
if (!m_instance)
|
|
||||||
m_instance = new PortForwarder(provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PortForwarder::freeInstance()
|
|
||||||
{
|
|
||||||
if (m_instance) {
|
|
||||||
delete m_instance;
|
|
||||||
m_instance = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PortForwarder *PortForwarder::instance()
|
|
||||||
{
|
{
|
||||||
return m_instance;
|
return m_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PortForwarder::isEnabled() const
|
Net::PortForwarder *Net::PortForwarder::m_instance = nullptr;
|
||||||
{
|
|
||||||
return m_active;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PortForwarder::setEnabled(const bool enabled)
|
|
||||||
{
|
|
||||||
if (m_active != enabled) {
|
|
||||||
if (enabled)
|
|
||||||
start();
|
|
||||||
else
|
|
||||||
stop();
|
|
||||||
|
|
||||||
SettingsStorage::instance()->storeValue(KEY_ENABLED, enabled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PortForwarder::addPort(const quint16 port)
|
|
||||||
{
|
|
||||||
if (!m_mappedPorts.contains(port)) {
|
|
||||||
m_mappedPorts.insert(port, 0);
|
|
||||||
if (m_active)
|
|
||||||
m_mappedPorts[port] = m_provider->add_port_mapping(libt::session::tcp, port, port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PortForwarder::deletePort(const quint16 port)
|
|
||||||
{
|
|
||||||
if (m_mappedPorts.contains(port)) {
|
|
||||||
if (m_active)
|
|
||||||
m_provider->delete_port_mapping(m_mappedPorts[port]);
|
|
||||||
m_mappedPorts.remove(port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PortForwarder::start()
|
|
||||||
{
|
|
||||||
qDebug("Enabling UPnP / NAT-PMP");
|
|
||||||
libt::settings_pack settingsPack = m_provider->get_settings();
|
|
||||||
settingsPack.set_bool(libt::settings_pack::enable_upnp, true);
|
|
||||||
settingsPack.set_bool(libt::settings_pack::enable_natpmp, true);
|
|
||||||
m_provider->apply_settings(settingsPack);
|
|
||||||
for (auto i = m_mappedPorts.begin(); i != m_mappedPorts.end(); ++i) {
|
|
||||||
// quint16 port = i.key();
|
|
||||||
i.value() = m_provider->add_port_mapping(libt::session::tcp, i.key(), i.key());
|
|
||||||
}
|
|
||||||
m_active = true;
|
|
||||||
Logger::instance()->addMessage(tr("UPnP / NAT-PMP support [ON]"), Log::INFO);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PortForwarder::stop()
|
|
||||||
{
|
|
||||||
qDebug("Disabling UPnP / NAT-PMP");
|
|
||||||
libt::settings_pack settingsPack = m_provider->get_settings();
|
|
||||||
settingsPack.set_bool(libt::settings_pack::enable_upnp, false);
|
|
||||||
settingsPack.set_bool(libt::settings_pack::enable_natpmp, false);
|
|
||||||
m_provider->apply_settings(settingsPack);
|
|
||||||
m_active = false;
|
|
||||||
Logger::instance()->addMessage(tr("UPnP / NAT-PMP support [OFF]"), Log::INFO);
|
|
||||||
}
|
|
||||||
|
|
||||||
PortForwarder *PortForwarder::m_instance = nullptr;
|
|
||||||
|
@ -29,43 +29,27 @@
|
|||||||
#ifndef NET_PORTFORWARDER_H
|
#ifndef NET_PORTFORWARDER_H
|
||||||
#define NET_PORTFORWARDER_H
|
#define NET_PORTFORWARDER_H
|
||||||
|
|
||||||
#include <QHash>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
namespace libtorrent
|
|
||||||
{
|
|
||||||
class session;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Net
|
namespace Net
|
||||||
{
|
{
|
||||||
class PortForwarder : public QObject
|
class PortForwarder : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
|
||||||
Q_DISABLE_COPY(PortForwarder)
|
Q_DISABLE_COPY(PortForwarder)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void initInstance(libtorrent::session *const provider);
|
explicit PortForwarder(QObject *parent = nullptr);
|
||||||
static void freeInstance();
|
~PortForwarder() override;
|
||||||
|
|
||||||
static PortForwarder *instance();
|
static PortForwarder *instance();
|
||||||
|
|
||||||
bool isEnabled() const;
|
virtual bool isEnabled() const = 0;
|
||||||
void setEnabled(bool enabled);
|
virtual void setEnabled(bool enabled) = 0;
|
||||||
|
|
||||||
void addPort(quint16 port);
|
virtual void addPort(quint16 port) = 0;
|
||||||
void deletePort(quint16 port);
|
virtual void deletePort(quint16 port) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit PortForwarder(libtorrent::session *const provider, QObject *parent = nullptr);
|
|
||||||
~PortForwarder();
|
|
||||||
|
|
||||||
void start();
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
bool m_active;
|
|
||||||
libtorrent::session *m_provider;
|
|
||||||
QHash<quint16, int> m_mappedPorts;
|
|
||||||
|
|
||||||
static PortForwarder *m_instance;
|
static PortForwarder *m_instance;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
#include "base/bittorrent/filepriority.h"
|
#include "base/bittorrent/downloadpriority.h"
|
||||||
#include "base/bittorrent/magneturi.h"
|
#include "base/bittorrent/magneturi.h"
|
||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/bittorrent/torrenthandle.h"
|
#include "base/bittorrent/torrenthandle.h"
|
||||||
@ -420,10 +420,10 @@ void AddNewTorrentDialog::updateDiskSpaceLabel()
|
|||||||
|
|
||||||
if (m_hasMetadata) {
|
if (m_hasMetadata) {
|
||||||
if (m_contentModel) {
|
if (m_contentModel) {
|
||||||
const QVector<int> priorities = m_contentModel->model()->getFilePriorities();
|
const QVector<BitTorrent::DownloadPriority> priorities = m_contentModel->model()->getFilePriorities();
|
||||||
Q_ASSERT(priorities.size() == m_torrentInfo.filesCount());
|
Q_ASSERT(priorities.size() == m_torrentInfo.filesCount());
|
||||||
for (int i = 0; i < priorities.size(); ++i)
|
for (int i = 0; i < priorities.size(); ++i)
|
||||||
if (priorities[i] > 0)
|
if (priorities[i] > BitTorrent::DownloadPriority::Ignored)
|
||||||
torrentSize += m_torrentInfo.fileSize(i);
|
torrentSize += m_torrentInfo.fileSize(i);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -612,13 +612,13 @@ void AddNewTorrentDialog::displayContentTreeMenu(const QPoint &)
|
|||||||
renameSelectedFile();
|
renameSelectedFile();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BitTorrent::FilePriority prio = BitTorrent::FilePriority::Normal;
|
BitTorrent::DownloadPriority prio = BitTorrent::DownloadPriority::Normal;
|
||||||
if (act == m_ui->actionHigh)
|
if (act == m_ui->actionHigh)
|
||||||
prio = BitTorrent::FilePriority::High;
|
prio = BitTorrent::DownloadPriority::High;
|
||||||
else if (act == m_ui->actionMaximum)
|
else if (act == m_ui->actionMaximum)
|
||||||
prio = BitTorrent::FilePriority::Maximum;
|
prio = BitTorrent::DownloadPriority::Maximum;
|
||||||
else if (act == m_ui->actionNotDownloaded)
|
else if (act == m_ui->actionNotDownloaded)
|
||||||
prio = BitTorrent::FilePriority::Ignored;
|
prio = BitTorrent::DownloadPriority::Ignored;
|
||||||
|
|
||||||
qDebug("Setting files priority");
|
qDebug("Setting files priority");
|
||||||
for (const QModelIndex &index : selectedRows) {
|
for (const QModelIndex &index : selectedRows) {
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include "base/bittorrent/filepriority.h"
|
#include "base/bittorrent/downloadpriority.h"
|
||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/preferences.h"
|
#include "base/preferences.h"
|
||||||
#include "base/unicodestrings.h"
|
#include "base/unicodestrings.h"
|
||||||
@ -621,13 +621,13 @@ void PropertiesWidget::displayFilesListMenu(const QPoint &)
|
|||||||
renameSelectedFile();
|
renameSelectedFile();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BitTorrent::FilePriority prio = BitTorrent::FilePriority::Normal;
|
BitTorrent::DownloadPriority prio = BitTorrent::DownloadPriority::Normal;
|
||||||
if (act == m_ui->actionHigh)
|
if (act == m_ui->actionHigh)
|
||||||
prio = BitTorrent::FilePriority::High;
|
prio = BitTorrent::DownloadPriority::High;
|
||||||
else if (act == m_ui->actionMaximum)
|
else if (act == m_ui->actionMaximum)
|
||||||
prio = BitTorrent::FilePriority::Maximum;
|
prio = BitTorrent::DownloadPriority::Maximum;
|
||||||
else if (act == m_ui->actionNotDownloaded)
|
else if (act == m_ui->actionNotDownloaded)
|
||||||
prio = BitTorrent::FilePriority::Ignored;
|
prio = BitTorrent::DownloadPriority::Ignored;
|
||||||
|
|
||||||
qDebug("Setting files priority");
|
qDebug("Setting files priority");
|
||||||
for (const QModelIndex &index : selectedRows) {
|
for (const QModelIndex &index : selectedRows) {
|
||||||
@ -894,11 +894,7 @@ void PropertiesWidget::editWebSeed()
|
|||||||
|
|
||||||
void PropertiesWidget::applyPriorities()
|
void PropertiesWidget::applyPriorities()
|
||||||
{
|
{
|
||||||
qDebug("Saving files priorities");
|
m_torrent->prioritizeFiles(m_propListModel->model()->getFilePriorities());
|
||||||
const QVector<int> priorities = m_propListModel->model()->getFilePriorities();
|
|
||||||
// Prioritize the files
|
|
||||||
qDebug("prioritize files: %d", priorities[0]);
|
|
||||||
m_torrent->prioritizeFiles(priorities);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertiesWidget::filteredFilesChanged()
|
void PropertiesWidget::filteredFilesChanged()
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
#include <QProxyStyle>
|
#include <QProxyStyle>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "base/bittorrent/filepriority.h"
|
#include "base/bittorrent/downloadpriority.h"
|
||||||
#include "base/unicodestrings.h"
|
#include "base/unicodestrings.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "base/utils/string.h"
|
#include "base/utils/string.h"
|
||||||
@ -93,7 +93,7 @@ void PropListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
|
|||||||
newopt.maximum = 100;
|
newopt.maximum = 100;
|
||||||
newopt.minimum = 0;
|
newopt.minimum = 0;
|
||||||
newopt.textVisible = true;
|
newopt.textVisible = true;
|
||||||
if (index.sibling(index.row(), PRIORITY).data().toInt() == static_cast<int>(BitTorrent::FilePriority::Ignored)) {
|
if (index.sibling(index.row(), PRIORITY).data().toInt() == static_cast<int>(BitTorrent::DownloadPriority::Ignored)) {
|
||||||
newopt.state &= ~QStyle::State_Enabled;
|
newopt.state &= ~QStyle::State_Enabled;
|
||||||
newopt.palette = progressBarDisabledPalette();
|
newopt.palette = progressBarDisabledPalette();
|
||||||
}
|
}
|
||||||
@ -111,17 +111,17 @@ void PropListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
|
|||||||
break;
|
break;
|
||||||
case PRIORITY: {
|
case PRIORITY: {
|
||||||
QString text = "";
|
QString text = "";
|
||||||
switch (static_cast<BitTorrent::FilePriority>(index.data().toInt())) {
|
switch (static_cast<BitTorrent::DownloadPriority>(index.data().toInt())) {
|
||||||
case BitTorrent::FilePriority::Mixed:
|
case BitTorrent::DownloadPriority::Mixed:
|
||||||
text = tr("Mixed", "Mixed (priorities");
|
text = tr("Mixed", "Mixed (priorities");
|
||||||
break;
|
break;
|
||||||
case BitTorrent::FilePriority::Ignored:
|
case BitTorrent::DownloadPriority::Ignored:
|
||||||
text = tr("Not downloaded");
|
text = tr("Not downloaded");
|
||||||
break;
|
break;
|
||||||
case BitTorrent::FilePriority::High:
|
case BitTorrent::DownloadPriority::High:
|
||||||
text = tr("High", "High (priority)");
|
text = tr("High", "High (priority)");
|
||||||
break;
|
break;
|
||||||
case BitTorrent::FilePriority::Maximum:
|
case BitTorrent::DownloadPriority::Maximum:
|
||||||
text = tr("Maximum", "Maximum (priority)");
|
text = tr("Maximum", "Maximum (priority)");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -155,14 +155,14 @@ void PropListDelegate::setEditorData(QWidget *editor, const QModelIndex &index)
|
|||||||
{
|
{
|
||||||
auto *combobox = static_cast<QComboBox *>(editor);
|
auto *combobox = static_cast<QComboBox *>(editor);
|
||||||
// Set combobox index
|
// Set combobox index
|
||||||
switch (static_cast<BitTorrent::FilePriority>(index.data().toInt())) {
|
switch (static_cast<BitTorrent::DownloadPriority>(index.data().toInt())) {
|
||||||
case BitTorrent::FilePriority::Ignored:
|
case BitTorrent::DownloadPriority::Ignored:
|
||||||
combobox->setCurrentIndex(0);
|
combobox->setCurrentIndex(0);
|
||||||
break;
|
break;
|
||||||
case BitTorrent::FilePriority::High:
|
case BitTorrent::DownloadPriority::High:
|
||||||
combobox->setCurrentIndex(2);
|
combobox->setCurrentIndex(2);
|
||||||
break;
|
break;
|
||||||
case BitTorrent::FilePriority::Maximum:
|
case BitTorrent::DownloadPriority::Maximum:
|
||||||
combobox->setCurrentIndex(3);
|
combobox->setCurrentIndex(3);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -181,7 +181,7 @@ QWidget *PropListDelegate::createEditor(QWidget *parent, const QStyleOptionViewI
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index.data().toInt() == static_cast<int>(BitTorrent::FilePriority::Mixed))
|
if (index.data().toInt() == static_cast<int>(BitTorrent::DownloadPriority::Mixed))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto *editor = new QComboBox(parent);
|
auto *editor = new QComboBox(parent);
|
||||||
@ -199,16 +199,16 @@ void PropListDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
|
|||||||
int value = combobox->currentIndex();
|
int value = combobox->currentIndex();
|
||||||
qDebug("PropListDelegate: setModelData(%d)", value);
|
qDebug("PropListDelegate: setModelData(%d)", value);
|
||||||
|
|
||||||
BitTorrent::FilePriority prio = BitTorrent::FilePriority::Normal; // NORMAL
|
BitTorrent::DownloadPriority prio = BitTorrent::DownloadPriority::Normal; // NORMAL
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case 0:
|
case 0:
|
||||||
prio = BitTorrent::FilePriority::Ignored; // IGNORED
|
prio = BitTorrent::DownloadPriority::Ignored; // IGNORED
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
prio = BitTorrent::FilePriority::High; // HIGH
|
prio = BitTorrent::DownloadPriority::High; // HIGH
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
prio = BitTorrent::FilePriority::Maximum; // MAX
|
prio = BitTorrent::DownloadPriority::Maximum; // MAX
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,9 +367,9 @@ void TrackerListWidget::loadTrackers()
|
|||||||
}
|
}
|
||||||
|
|
||||||
item->setText(COL_PEERS, QString::number(data.numPeers));
|
item->setText(COL_PEERS, QString::number(data.numPeers));
|
||||||
item->setText(COL_SEEDS, (entry.nativeEntry().scrape_complete > -1) ? QString::number(entry.nativeEntry().scrape_complete) : tr("N/A"));
|
item->setText(COL_SEEDS, (entry.numSeeds() > -1) ? QString::number(entry.numSeeds()) : tr("N/A"));
|
||||||
item->setText(COL_LEECHES, (entry.nativeEntry().scrape_incomplete > -1) ? QString::number(entry.nativeEntry().scrape_incomplete) : tr("N/A"));
|
item->setText(COL_LEECHES, (entry.numLeeches() > -1) ? QString::number(entry.numLeeches()) : tr("N/A"));
|
||||||
item->setText(COL_DOWNLOADED, (entry.nativeEntry().scrape_downloaded > -1) ? QString::number(entry.nativeEntry().scrape_downloaded) : tr("N/A"));
|
item->setText(COL_DOWNLOADED, (entry.numDownloaded() > -1) ? QString::number(entry.numDownloaded()) : tr("N/A"));
|
||||||
|
|
||||||
item->setTextAlignment(COL_TIER, (Qt::AlignRight | Qt::AlignVCenter));
|
item->setTextAlignment(COL_TIER, (Qt::AlignRight | Qt::AlignVCenter));
|
||||||
item->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter));
|
item->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter));
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
#include <QPixmapCache>
|
#include <QPixmapCache>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "base/bittorrent/filepriority.h"
|
#include "base/bittorrent/downloadpriority.h"
|
||||||
#include "base/global.h"
|
#include "base/global.h"
|
||||||
#include "base/utils/misc.h"
|
#include "base/utils/misc.h"
|
||||||
#include "base/utils/fs.h"
|
#include "base/utils/fs.h"
|
||||||
@ -239,7 +239,7 @@ void TorrentContentModel::updateFilesProgress(const QVector<qreal> &fp)
|
|||||||
emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
|
emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentContentModel::updateFilesPriorities(const QVector<int> &fprio)
|
void TorrentContentModel::updateFilesPriorities(const QVector<BitTorrent::DownloadPriority> &fprio)
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_filesIndex.size() == fprio.size());
|
Q_ASSERT(m_filesIndex.size() == fprio.size());
|
||||||
// XXX: Why is this necessary?
|
// XXX: Why is this necessary?
|
||||||
@ -248,7 +248,7 @@ void TorrentContentModel::updateFilesPriorities(const QVector<int> &fprio)
|
|||||||
|
|
||||||
emit layoutAboutToBeChanged();
|
emit layoutAboutToBeChanged();
|
||||||
for (int i = 0; i < fprio.size(); ++i)
|
for (int i = 0; i < fprio.size(); ++i)
|
||||||
m_filesIndex[i]->setPriority(static_cast<BitTorrent::FilePriority>(fprio[i]));
|
m_filesIndex[i]->setPriority(static_cast<BitTorrent::DownloadPriority>(fprio[i]));
|
||||||
emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
|
emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,12 +266,12 @@ void TorrentContentModel::updateFilesAvailability(const QVector<qreal> &fa)
|
|||||||
emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
|
emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<int> TorrentContentModel::getFilePriorities() const
|
QVector<BitTorrent::DownloadPriority> TorrentContentModel::getFilePriorities() const
|
||||||
{
|
{
|
||||||
QVector<int> prio;
|
QVector<BitTorrent::DownloadPriority> prio;
|
||||||
prio.reserve(m_filesIndex.size());
|
prio.reserve(m_filesIndex.size());
|
||||||
for (const TorrentContentModelFile *file : asConst(m_filesIndex))
|
for (const TorrentContentModelFile *file : asConst(m_filesIndex))
|
||||||
prio.push_back(static_cast<int>(file->priority()));
|
prio.push_back(file->priority());
|
||||||
return prio;
|
return prio;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +279,7 @@ bool TorrentContentModel::allFiltered() const
|
|||||||
{
|
{
|
||||||
return std::all_of(m_filesIndex.cbegin(), m_filesIndex.cend(), [](const TorrentContentModelFile *fileItem)
|
return std::all_of(m_filesIndex.cbegin(), m_filesIndex.cend(), [](const TorrentContentModelFile *fileItem)
|
||||||
{
|
{
|
||||||
return (fileItem->priority() == BitTorrent::FilePriority::Ignored);
|
return (fileItem->priority() == BitTorrent::DownloadPriority::Ignored);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,11 +300,11 @@ bool TorrentContentModel::setData(const QModelIndex &index, const QVariant &valu
|
|||||||
auto *item = static_cast<TorrentContentModelItem*>(index.internalPointer());
|
auto *item = static_cast<TorrentContentModelItem*>(index.internalPointer());
|
||||||
qDebug("setData(%s, %d", qUtf8Printable(item->name()), value.toInt());
|
qDebug("setData(%s, %d", qUtf8Printable(item->name()), value.toInt());
|
||||||
if (static_cast<int>(item->priority()) != value.toInt()) {
|
if (static_cast<int>(item->priority()) != value.toInt()) {
|
||||||
BitTorrent::FilePriority prio = BitTorrent::FilePriority::Normal;
|
BitTorrent::DownloadPriority prio = BitTorrent::DownloadPriority::Normal;
|
||||||
if (value.toInt() == Qt::PartiallyChecked)
|
if (value.toInt() == Qt::PartiallyChecked)
|
||||||
prio = BitTorrent::FilePriority::Mixed;
|
prio = BitTorrent::DownloadPriority::Mixed;
|
||||||
else if (value.toInt() == Qt::Unchecked)
|
else if (value.toInt() == Qt::Unchecked)
|
||||||
prio = BitTorrent::FilePriority::Ignored;
|
prio = BitTorrent::DownloadPriority::Ignored;
|
||||||
|
|
||||||
item->setPriority(prio);
|
item->setPriority(prio);
|
||||||
// Update folders progress in the tree
|
// Update folders progress in the tree
|
||||||
@ -324,7 +324,7 @@ bool TorrentContentModel::setData(const QModelIndex &index, const QVariant &valu
|
|||||||
item->setName(value.toString());
|
item->setName(value.toString());
|
||||||
break;
|
break;
|
||||||
case TorrentContentModelItem::COL_PRIO:
|
case TorrentContentModelItem::COL_PRIO:
|
||||||
item->setPriority(static_cast<BitTorrent::FilePriority>(value.toInt()));
|
item->setPriority(static_cast<BitTorrent::DownloadPriority>(value.toInt()));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@ -366,9 +366,9 @@ QVariant TorrentContentModel::data(const QModelIndex &index, int role) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((index.column() == TorrentContentModelItem::COL_NAME) && (role == Qt::CheckStateRole)) {
|
if ((index.column() == TorrentContentModelItem::COL_NAME) && (role == Qt::CheckStateRole)) {
|
||||||
if (item->data(TorrentContentModelItem::COL_PRIO).toInt() == static_cast<int>(BitTorrent::FilePriority::Ignored))
|
if (item->data(TorrentContentModelItem::COL_PRIO).toInt() == static_cast<int>(BitTorrent::DownloadPriority::Ignored))
|
||||||
return Qt::Unchecked;
|
return Qt::Unchecked;
|
||||||
if (item->data(TorrentContentModelItem::COL_PRIO).toInt() == static_cast<int>(BitTorrent::FilePriority::Mixed))
|
if (item->data(TorrentContentModelItem::COL_PRIO).toInt() == static_cast<int>(BitTorrent::DownloadPriority::Mixed))
|
||||||
return Qt::PartiallyChecked;
|
return Qt::PartiallyChecked;
|
||||||
return Qt::Checked;
|
return Qt::Checked;
|
||||||
}
|
}
|
||||||
@ -503,8 +503,8 @@ void TorrentContentModel::selectAll()
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < m_rootItem->childCount(); ++i) {
|
for (int i = 0; i < m_rootItem->childCount(); ++i) {
|
||||||
TorrentContentModelItem* child = m_rootItem->child(i);
|
TorrentContentModelItem* child = m_rootItem->child(i);
|
||||||
if (child->priority() == BitTorrent::FilePriority::Ignored)
|
if (child->priority() == BitTorrent::DownloadPriority::Ignored)
|
||||||
child->setPriority(BitTorrent::FilePriority::Normal);
|
child->setPriority(BitTorrent::DownloadPriority::Normal);
|
||||||
}
|
}
|
||||||
emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
|
emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
|
||||||
}
|
}
|
||||||
@ -512,6 +512,6 @@ void TorrentContentModel::selectAll()
|
|||||||
void TorrentContentModel::selectNone()
|
void TorrentContentModel::selectNone()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_rootItem->childCount(); ++i)
|
for (int i = 0; i < m_rootItem->childCount(); ++i)
|
||||||
m_rootItem->child(i)->setPriority(BitTorrent::FilePriority::Ignored);
|
m_rootItem->child(i)->setPriority(BitTorrent::DownloadPriority::Ignored);
|
||||||
emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
|
emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
|
||||||
}
|
}
|
||||||
|
@ -43,15 +43,16 @@ class TorrentContentModelFile;
|
|||||||
class TorrentContentModel : public QAbstractItemModel
|
class TorrentContentModel : public QAbstractItemModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY(TorrentContentModel)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TorrentContentModel(QObject *parent = nullptr);
|
TorrentContentModel(QObject *parent = nullptr);
|
||||||
~TorrentContentModel() override;
|
~TorrentContentModel() override;
|
||||||
|
|
||||||
void updateFilesProgress(const QVector<qreal> &fp);
|
void updateFilesProgress(const QVector<qreal> &fp);
|
||||||
void updateFilesPriorities(const QVector<int> &fprio);
|
void updateFilesPriorities(const QVector<BitTorrent::DownloadPriority> &fprio);
|
||||||
void updateFilesAvailability(const QVector<qreal> &fa);
|
void updateFilesAvailability(const QVector<qreal> &fa);
|
||||||
QVector<int> getFilePriorities() const;
|
QVector<BitTorrent::DownloadPriority> getFilePriorities() const;
|
||||||
bool allFiltered() const;
|
bool allFiltered() const;
|
||||||
int columnCount(const QModelIndex &parent = {}) const override;
|
int columnCount(const QModelIndex &parent = {}) const override;
|
||||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||||
|
@ -52,9 +52,9 @@ int TorrentContentModelFile::fileIndex() const
|
|||||||
return m_fileIndex;
|
return m_fileIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentContentModelFile::setPriority(BitTorrent::FilePriority newPriority, bool updateParent)
|
void TorrentContentModelFile::setPriority(BitTorrent::DownloadPriority newPriority, bool updateParent)
|
||||||
{
|
{
|
||||||
Q_ASSERT(newPriority != BitTorrent::FilePriority::Mixed);
|
Q_ASSERT(newPriority != BitTorrent::DownloadPriority::Mixed);
|
||||||
|
|
||||||
if (m_priority == newPriority)
|
if (m_priority == newPriority)
|
||||||
return;
|
return;
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#ifndef TORRENTCONTENTMODELFILE_H
|
#ifndef TORRENTCONTENTMODELFILE_H
|
||||||
#define TORRENTCONTENTMODELFILE_H
|
#define TORRENTCONTENTMODELFILE_H
|
||||||
|
|
||||||
#include "base/bittorrent/filepriority.h"
|
#include "base/bittorrent/downloadpriority.h"
|
||||||
#include "torrentcontentmodelitem.h"
|
#include "torrentcontentmodelitem.h"
|
||||||
|
|
||||||
class TorrentContentModelFile : public TorrentContentModelItem
|
class TorrentContentModelFile : public TorrentContentModelItem
|
||||||
@ -39,7 +39,7 @@ public:
|
|||||||
TorrentContentModelFolder *parent, int fileIndex);
|
TorrentContentModelFolder *parent, int fileIndex);
|
||||||
|
|
||||||
int fileIndex() const;
|
int fileIndex() const;
|
||||||
void setPriority(BitTorrent::FilePriority newPriority, bool updateParent = true) override;
|
void setPriority(BitTorrent::DownloadPriority newPriority, bool updateParent = true) override;
|
||||||
void setProgress(qreal progress);
|
void setProgress(qreal progress);
|
||||||
void setAvailability(qreal availability);
|
void setAvailability(qreal availability);
|
||||||
ItemType itemType() const override;
|
ItemType itemType() const override;
|
||||||
|
@ -109,10 +109,10 @@ void TorrentContentModelFolder::updatePriority()
|
|||||||
// If all children have the same priority
|
// If all children have the same priority
|
||||||
// then the folder should have the same
|
// then the folder should have the same
|
||||||
// priority
|
// priority
|
||||||
const BitTorrent::FilePriority prio = m_childItems.first()->priority();
|
const BitTorrent::DownloadPriority prio = m_childItems.first()->priority();
|
||||||
for (int i = 1; i < m_childItems.size(); ++i) {
|
for (int i = 1; i < m_childItems.size(); ++i) {
|
||||||
if (m_childItems.at(i)->priority() != prio) {
|
if (m_childItems.at(i)->priority() != prio) {
|
||||||
setPriority(BitTorrent::FilePriority::Mixed);
|
setPriority(BitTorrent::DownloadPriority::Mixed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ void TorrentContentModelFolder::updatePriority()
|
|||||||
setPriority(prio);
|
setPriority(prio);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TorrentContentModelFolder::setPriority(BitTorrent::FilePriority newPriority, bool updateParent)
|
void TorrentContentModelFolder::setPriority(BitTorrent::DownloadPriority newPriority, bool updateParent)
|
||||||
{
|
{
|
||||||
if (m_priority == newPriority)
|
if (m_priority == newPriority)
|
||||||
return;
|
return;
|
||||||
@ -133,7 +133,7 @@ void TorrentContentModelFolder::setPriority(BitTorrent::FilePriority newPriority
|
|||||||
m_parentItem->updatePriority();
|
m_parentItem->updatePriority();
|
||||||
|
|
||||||
// Update children
|
// Update children
|
||||||
if (m_priority != BitTorrent::FilePriority::Mixed)
|
if (m_priority != BitTorrent::DownloadPriority::Mixed)
|
||||||
for (TorrentContentModelItem *child : asConst(m_childItems))
|
for (TorrentContentModelItem *child : asConst(m_childItems))
|
||||||
child->setPriority(m_priority, false);
|
child->setPriority(m_priority, false);
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ void TorrentContentModelFolder::recalculateProgress()
|
|||||||
qulonglong tSize = 0;
|
qulonglong tSize = 0;
|
||||||
qulonglong tRemaining = 0;
|
qulonglong tRemaining = 0;
|
||||||
for (TorrentContentModelItem *child : asConst(m_childItems)) {
|
for (TorrentContentModelItem *child : asConst(m_childItems)) {
|
||||||
if (child->priority() == BitTorrent::FilePriority::Ignored)
|
if (child->priority() == BitTorrent::DownloadPriority::Ignored)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (child->itemType() == FolderType)
|
if (child->itemType() == FolderType)
|
||||||
@ -167,7 +167,7 @@ void TorrentContentModelFolder::recalculateAvailability()
|
|||||||
qulonglong tSize = 0;
|
qulonglong tSize = 0;
|
||||||
bool foundAnyData = false;
|
bool foundAnyData = false;
|
||||||
for (TorrentContentModelItem *child : asConst(m_childItems)) {
|
for (TorrentContentModelItem *child : asConst(m_childItems)) {
|
||||||
if (child->priority() == BitTorrent::FilePriority::Ignored)
|
if (child->priority() == BitTorrent::DownloadPriority::Ignored)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (child->itemType() == FolderType)
|
if (child->itemType() == FolderType)
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#ifndef TORRENTCONTENTMODELFOLDER_H
|
#ifndef TORRENTCONTENTMODELFOLDER_H
|
||||||
#define TORRENTCONTENTMODELFOLDER_H
|
#define TORRENTCONTENTMODELFOLDER_H
|
||||||
|
|
||||||
#include "base/bittorrent/filepriority.h"
|
#include "base/bittorrent/downloadpriority.h"
|
||||||
#include "torrentcontentmodelitem.h"
|
#include "torrentcontentmodelitem.h"
|
||||||
|
|
||||||
class TorrentContentModelFolder : public TorrentContentModelItem
|
class TorrentContentModelFolder : public TorrentContentModelItem
|
||||||
@ -50,7 +50,7 @@ public:
|
|||||||
void recalculateAvailability();
|
void recalculateAvailability();
|
||||||
void updatePriority();
|
void updatePriority();
|
||||||
|
|
||||||
void setPriority(BitTorrent::FilePriority newPriority, bool updateParent = true) override;
|
void setPriority(BitTorrent::DownloadPriority newPriority, bool updateParent = true) override;
|
||||||
|
|
||||||
void deleteAllChildren();
|
void deleteAllChildren();
|
||||||
const QList<TorrentContentModelItem*> &children() const;
|
const QList<TorrentContentModelItem*> &children() const;
|
||||||
|
@ -38,7 +38,7 @@ TorrentContentModelItem::TorrentContentModelItem(TorrentContentModelFolder *pare
|
|||||||
: m_parentItem(parent)
|
: m_parentItem(parent)
|
||||||
, m_size(0)
|
, m_size(0)
|
||||||
, m_remaining(0)
|
, m_remaining(0)
|
||||||
, m_priority(BitTorrent::FilePriority::Normal)
|
, m_priority(BitTorrent::DownloadPriority::Normal)
|
||||||
, m_progress(0)
|
, m_progress(0)
|
||||||
, m_availability(-1.)
|
, m_availability(-1.)
|
||||||
{
|
{
|
||||||
@ -90,7 +90,7 @@ qreal TorrentContentModelItem::availability() const
|
|||||||
return (m_size > 0) ? m_availability : 0;
|
return (m_size > 0) ? m_availability : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BitTorrent::FilePriority TorrentContentModelItem::priority() const
|
BitTorrent::DownloadPriority TorrentContentModelItem::priority() const
|
||||||
{
|
{
|
||||||
Q_ASSERT(!isRootItem());
|
Q_ASSERT(!isRootItem());
|
||||||
return m_priority;
|
return m_priority;
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
#include "base/bittorrent/filepriority.h"
|
#include "base/bittorrent/downloadpriority.h"
|
||||||
|
|
||||||
class TorrentContentModelFolder;
|
class TorrentContentModelFolder;
|
||||||
|
|
||||||
@ -72,8 +72,8 @@ public:
|
|||||||
|
|
||||||
qreal availability() const;
|
qreal availability() const;
|
||||||
|
|
||||||
BitTorrent::FilePriority priority() const;
|
BitTorrent::DownloadPriority priority() const;
|
||||||
virtual void setPriority(BitTorrent::FilePriority newPriority, bool updateParent = true) = 0;
|
virtual void setPriority(BitTorrent::DownloadPriority newPriority, bool updateParent = true) = 0;
|
||||||
|
|
||||||
int columnCount() const;
|
int columnCount() const;
|
||||||
QVariant data(int column) const;
|
QVariant data(int column) const;
|
||||||
@ -87,7 +87,7 @@ protected:
|
|||||||
QString m_name;
|
QString m_name;
|
||||||
qulonglong m_size;
|
qulonglong m_size;
|
||||||
qulonglong m_remaining;
|
qulonglong m_remaining;
|
||||||
BitTorrent::FilePriority m_priority;
|
BitTorrent::DownloadPriority m_priority;
|
||||||
qreal m_progress;
|
qreal m_progress;
|
||||||
qreal m_availability;
|
qreal m_availability;
|
||||||
};
|
};
|
||||||
|
@ -92,7 +92,7 @@ QVariantMap serialize(const BitTorrent::TorrentHandle &torrent)
|
|||||||
ret[KEY_TORRENT_PROGRESS] = torrent.progress();
|
ret[KEY_TORRENT_PROGRESS] = torrent.progress();
|
||||||
ret[KEY_TORRENT_DLSPEED] = torrent.downloadPayloadRate();
|
ret[KEY_TORRENT_DLSPEED] = torrent.downloadPayloadRate();
|
||||||
ret[KEY_TORRENT_UPSPEED] = torrent.uploadPayloadRate();
|
ret[KEY_TORRENT_UPSPEED] = torrent.uploadPayloadRate();
|
||||||
ret[KEY_TORRENT_PRIORITY] = torrent.queuePosition();
|
ret[KEY_TORRENT_PRIORITY] = static_cast<int>(torrent.queuePosition());
|
||||||
ret[KEY_TORRENT_SEEDS] = torrent.seedsCount();
|
ret[KEY_TORRENT_SEEDS] = torrent.seedsCount();
|
||||||
ret[KEY_TORRENT_NUM_COMPLETE] = torrent.totalSeedsCount();
|
ret[KEY_TORRENT_NUM_COMPLETE] = torrent.totalSeedsCount();
|
||||||
ret[KEY_TORRENT_LEECHS] = torrent.leechsCount();
|
ret[KEY_TORRENT_LEECHS] = torrent.leechsCount();
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include "base/bittorrent/filepriority.h"
|
#include "base/bittorrent/downloadpriority.h"
|
||||||
#include "base/bittorrent/peerinfo.h"
|
#include "base/bittorrent/peerinfo.h"
|
||||||
#include "base/bittorrent/session.h"
|
#include "base/bittorrent/session.h"
|
||||||
#include "base/bittorrent/torrenthandle.h"
|
#include "base/bittorrent/torrenthandle.h"
|
||||||
@ -393,9 +393,9 @@ void TorrentsController::trackersAction()
|
|||||||
{KEY_TRACKER_STATUS, static_cast<int>(tracker.status())},
|
{KEY_TRACKER_STATUS, static_cast<int>(tracker.status())},
|
||||||
{KEY_TRACKER_PEERS_COUNT, data.numPeers},
|
{KEY_TRACKER_PEERS_COUNT, data.numPeers},
|
||||||
{KEY_TRACKER_MSG, data.lastMessage.trimmed()},
|
{KEY_TRACKER_MSG, data.lastMessage.trimmed()},
|
||||||
{KEY_TRACKER_SEEDS_COUNT, tracker.nativeEntry().scrape_complete},
|
{KEY_TRACKER_SEEDS_COUNT, tracker.numSeeds()},
|
||||||
{KEY_TRACKER_LEECHES_COUNT, tracker.nativeEntry().scrape_incomplete},
|
{KEY_TRACKER_LEECHES_COUNT, tracker.numLeeches()},
|
||||||
{KEY_TRACKER_DOWNLOADED_COUNT, tracker.nativeEntry().scrape_downloaded}
|
{KEY_TRACKER_DOWNLOADED_COUNT, tracker.numDownloaded()}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,14 +446,14 @@ void TorrentsController::filesAction()
|
|||||||
throw APIError(APIErrorType::NotFound);
|
throw APIError(APIErrorType::NotFound);
|
||||||
|
|
||||||
if (torrent->hasMetadata()) {
|
if (torrent->hasMetadata()) {
|
||||||
const QVector<int> priorities = torrent->filePriorities();
|
const QVector<BitTorrent::DownloadPriority> priorities = torrent->filePriorities();
|
||||||
const QVector<qreal> fp = torrent->filesProgress();
|
const QVector<qreal> fp = torrent->filesProgress();
|
||||||
const QVector<qreal> fileAvailability = torrent->availableFileFractions();
|
const QVector<qreal> fileAvailability = torrent->availableFileFractions();
|
||||||
const BitTorrent::TorrentInfo info = torrent->info();
|
const BitTorrent::TorrentInfo info = torrent->info();
|
||||||
for (int i = 0; i < torrent->filesCount(); ++i) {
|
for (int i = 0; i < torrent->filesCount(); ++i) {
|
||||||
QVariantMap fileDict;
|
QVariantMap fileDict;
|
||||||
fileDict[KEY_FILE_PROGRESS] = fp[i];
|
fileDict[KEY_FILE_PROGRESS] = fp[i];
|
||||||
fileDict[KEY_FILE_PRIORITY] = priorities[i];
|
fileDict[KEY_FILE_PRIORITY] = static_cast<int>(priorities[i]);
|
||||||
fileDict[KEY_FILE_SIZE] = torrent->fileSize(i);
|
fileDict[KEY_FILE_SIZE] = torrent->fileSize(i);
|
||||||
fileDict[KEY_FILE_AVAILABILITY] = fileAvailability[i];
|
fileDict[KEY_FILE_AVAILABILITY] = fileAvailability[i];
|
||||||
|
|
||||||
@ -701,11 +701,11 @@ void TorrentsController::filePrioAction()
|
|||||||
|
|
||||||
const QString hash = params()["hash"];
|
const QString hash = params()["hash"];
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
const int priority = params()["priority"].toInt(&ok);
|
const auto priority = static_cast<BitTorrent::DownloadPriority>(params()["priority"].toInt(&ok));
|
||||||
if (!ok)
|
if (!ok)
|
||||||
throw APIError(APIErrorType::BadParams, tr("Priority must be an integer"));
|
throw APIError(APIErrorType::BadParams, tr("Priority must be an integer"));
|
||||||
|
|
||||||
if (!BitTorrent::isValidFilePriority(static_cast<BitTorrent::FilePriority>(priority)))
|
if (!BitTorrent::isValidDownloadPriority(priority))
|
||||||
throw APIError(APIErrorType::BadParams, tr("Priority is not valid"));
|
throw APIError(APIErrorType::BadParams, tr("Priority is not valid"));
|
||||||
|
|
||||||
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
|
||||||
@ -715,7 +715,7 @@ void TorrentsController::filePrioAction()
|
|||||||
throw APIError(APIErrorType::Conflict, tr("Torrent's metadata has not yet downloaded"));
|
throw APIError(APIErrorType::Conflict, tr("Torrent's metadata has not yet downloaded"));
|
||||||
|
|
||||||
const int filesCount = torrent->filesCount();
|
const int filesCount = torrent->filesCount();
|
||||||
QVector<int> priorities = torrent->filePriorities();
|
QVector<BitTorrent::DownloadPriority> priorities = torrent->filePriorities();
|
||||||
bool priorityChanged = false;
|
bool priorityChanged = false;
|
||||||
for (const QString &fileID : params()["id"].split('|')) {
|
for (const QString &fileID : params()["id"].split('|')) {
|
||||||
const int id = fileID.toInt(&ok);
|
const int id = fileID.toInt(&ok);
|
||||||
|
Loading…
Reference in New Issue
Block a user