Browse Source

Merge pull request #10373 from glassez/libtorrent-1.2

Add preliminary support of libtorrent v1.2
adaptive-webui-19844
Vladimir Golovnev 6 years ago committed by GitHub
parent
commit
6de02b0f2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      src/base/CMakeLists.txt
  2. 7
      src/base/base.pri
  3. 3
      src/base/bittorrent/addtorrentparams.h
  4. 14
      src/base/bittorrent/downloadpriority.cpp
  5. 5
      src/base/bittorrent/downloadpriority.h
  6. 6
      src/base/bittorrent/infohash.cpp
  7. 11
      src/base/bittorrent/infohash.h
  8. 8
      src/base/bittorrent/magneturi.cpp
  9. 53
      src/base/bittorrent/peerinfo.cpp
  10. 81
      src/base/bittorrent/private/libtorrentfwd.h
  11. 114
      src/base/bittorrent/private/portforwarderimpl.cpp
  12. 65
      src/base/bittorrent/private/portforwarderimpl.h
  13. 61
      src/base/bittorrent/session.cpp
  14. 44
      src/base/bittorrent/session.h
  15. 11
      src/base/bittorrent/torrentcreatorthread.cpp
  16. 93
      src/base/bittorrent/torrenthandle.cpp
  17. 33
      src/base/bittorrent/torrenthandle.h
  18. 39
      src/base/bittorrent/torrentinfo.cpp
  19. 11
      src/base/bittorrent/torrentinfo.h
  20. 49
      src/base/bittorrent/trackerentry.cpp
  21. 5
      src/base/bittorrent/trackerentry.h
  22. 103
      src/base/net/portforwarder.cpp
  23. 30
      src/base/net/portforwarder.h
  24. 14
      src/gui/addnewtorrentdialog.cpp
  25. 16
      src/gui/properties/propertieswidget.cpp
  26. 32
      src/gui/properties/proplistdelegate.cpp
  27. 6
      src/gui/properties/trackerlistwidget.cpp
  28. 32
      src/gui/torrentcontentmodel.cpp
  29. 5
      src/gui/torrentcontentmodel.h
  30. 4
      src/gui/torrentcontentmodelfile.cpp
  31. 4
      src/gui/torrentcontentmodelfile.h
  32. 12
      src/gui/torrentcontentmodelfolder.cpp
  33. 4
      src/gui/torrentcontentmodelfolder.h
  34. 4
      src/gui/torrentcontentmodelitem.cpp
  35. 8
      src/gui/torrentcontentmodelitem.h
  36. 2
      src/webui/api/serialize/serialize_torrent.cpp
  37. 18
      src/webui/api/torrentscontroller.cpp

7
src/base/CMakeLists.txt

@ -4,12 +4,14 @@ add_library(qbt_base STATIC @@ -4,12 +4,14 @@ add_library(qbt_base STATIC
# headers
bittorrent/addtorrentparams.h
bittorrent/cachestatus.h
bittorrent/filepriority.h
bittorrent/downloadpriority.h
bittorrent/infohash.h
bittorrent/magneturi.h
bittorrent/peerinfo.h
bittorrent/private/bandwidthscheduler.h
bittorrent/private/libtorrentfwd.h
bittorrent/private/filterparserthread.h
bittorrent/private/portforwarderimpl.h
bittorrent/private/resumedatasavingmanager.h
bittorrent/private/speedmonitor.h
bittorrent/private/statistics.h
@ -77,12 +79,13 @@ types.h @@ -77,12 +79,13 @@ types.h
unicodestrings.h
# sources
bittorrent/filepriority.cpp
bittorrent/downloadpriority.cpp
bittorrent/infohash.cpp
bittorrent/magneturi.cpp
bittorrent/peerinfo.cpp
bittorrent/private/bandwidthscheduler.cpp
bittorrent/private/filterparserthread.cpp
bittorrent/private/portforwarderimpl.cpp
bittorrent/private/resumedatasavingmanager.cpp
bittorrent/private/speedmonitor.cpp
bittorrent/private/statistics.cpp

7
src/base/base.pri

@ -3,12 +3,14 @@ HEADERS += \ @@ -3,12 +3,14 @@ HEADERS += \
$$PWD/asyncfilestorage.h \
$$PWD/bittorrent/addtorrentparams.h \
$$PWD/bittorrent/cachestatus.h \
$$PWD/bittorrent/filepriority.h \
$$PWD/bittorrent/downloadpriority.h \
$$PWD/bittorrent/infohash.h \
$$PWD/bittorrent/magneturi.h \
$$PWD/bittorrent/peerinfo.h \
$$PWD/bittorrent/private/bandwidthscheduler.h \
$$PWD/bittorrent/private/filterparserthread.h \
$$PWD/bittorrent/private/libtorrentfwd.h \
$$PWD/bittorrent/private/portforwarderimpl.h \
$$PWD/bittorrent/private/resumedatasavingmanager.h \
$$PWD/bittorrent/private/speedmonitor.h \
$$PWD/bittorrent/private/statistics.h \
@ -76,12 +78,13 @@ HEADERS += \ @@ -76,12 +78,13 @@ HEADERS += \
SOURCES += \
$$PWD/asyncfilestorage.cpp \
$$PWD/bittorrent/filepriority.cpp \
$$PWD/bittorrent/downloadpriority.cpp \
$$PWD/bittorrent/infohash.cpp \
$$PWD/bittorrent/magneturi.cpp \
$$PWD/bittorrent/peerinfo.cpp \
$$PWD/bittorrent/private/bandwidthscheduler.cpp \
$$PWD/bittorrent/private/filterparserthread.cpp \
$$PWD/bittorrent/private/portforwarderimpl.cpp \
$$PWD/bittorrent/private/resumedatasavingmanager.cpp \
$$PWD/bittorrent/private/speedmonitor.cpp \
$$PWD/bittorrent/private/statistics.cpp \

3
src/base/bittorrent/addtorrentparams.h

@ -33,6 +33,7 @@ @@ -33,6 +33,7 @@
#include <QVector>
#include "../tristatebool.h"
#include "downloadpriority.h"
namespace BitTorrent
{
@ -47,7 +48,7 @@ namespace BitTorrent @@ -47,7 +48,7 @@ namespace BitTorrent
bool firstLastPiecePriority = false;
TriStateBool addForced;
TriStateBool addPaused;
QVector<int> filePriorities; // used if TorrentInfo is set
QVector<DownloadPriority> filePriorities; // used if TorrentInfo is set
bool ignoreShareLimits = false;
bool skipChecking = false;
TriStateBool createSubfolder;

14
src/base/bittorrent/filepriority.cpp → src/base/bittorrent/downloadpriority.cpp

@ -26,18 +26,18 @@ @@ -26,18 +26,18 @@
* exception statement from your version.
*/
#include "filepriority.h"
#include "downloadpriority.h"
namespace BitTorrent
{
bool isValidFilePriority(const BitTorrent::FilePriority priority)
bool isValidDownloadPriority(const DownloadPriority priority)
{
switch (priority) {
case BitTorrent::FilePriority::Ignored:
case BitTorrent::FilePriority::Normal:
case BitTorrent::FilePriority::High:
case BitTorrent::FilePriority::Maximum:
case BitTorrent::FilePriority::Mixed:
case BitTorrent::DownloadPriority::Ignored:
case BitTorrent::DownloadPriority::Normal:
case BitTorrent::DownloadPriority::High:
case BitTorrent::DownloadPriority::Maximum:
case BitTorrent::DownloadPriority::Mixed:
return true;
default:
return false;

5
src/base/bittorrent/filepriority.h → src/base/bittorrent/downloadpriority.h

@ -30,14 +30,15 @@ @@ -30,14 +30,15 @@
namespace BitTorrent
{
enum class FilePriority : int
enum class DownloadPriority : int
{
Ignored = 0,
Normal = 1,
High = 6,
Maximum = 7,
Mixed = -1
};
bool isValidFilePriority(BitTorrent::FilePriority priority);
bool isValidDownloadPriority(DownloadPriority priority);
}

6
src/base/bittorrent/infohash.cpp

@ -42,18 +42,18 @@ InfoHash::InfoHash(const libtorrent::sha1_hash &nativeHash) @@ -42,18 +42,18 @@ InfoHash::InfoHash(const libtorrent::sha1_hash &nativeHash)
: m_valid(true)
, 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());
}
InfoHash::InfoHash(const QString &hashString)
: m_valid(false)
{
if (hashString.size() != (libtorrent::sha1_hash::size * 2))
if (hashString.size() != (length() * 2))
return;
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;
m_valid = true;

11
src/base/bittorrent/infohash.h

@ -30,6 +30,8 @@ @@ -30,6 +30,8 @@
#define BITTORRENT_INFOHASH_H
#include <libtorrent/sha1_hash.hpp>
#include <libtorrent/version.hpp>
#include <QString>
namespace BitTorrent
@ -42,6 +44,15 @@ namespace BitTorrent @@ -42,6 +44,15 @@ namespace BitTorrent
InfoHash(const QString &hashString);
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;
operator libtorrent::sha1_hash() const;

8
src/base/bittorrent/magneturi.cpp

@ -35,6 +35,8 @@ @@ -35,6 +35,8 @@
#include <QRegularExpression>
#include "infohash.h"
namespace
{
bool isBitTorrentInfoHash(const QString &string)
@ -44,8 +46,8 @@ namespace @@ -44,8 +46,8 @@ namespace
// == 20 (SHA-1 length in bytes) * 2 (each byte maps to 2 hex characters)
// 2. 32 chars Base32 encoded string
// == 20 (SHA-1 length in bytes) * 1.6 (the efficiency of Base32 encoding)
const int SHA1_HEX_SIZE = libtorrent::sha1_hash::size * 2;
const int SHA1_BASE32_SIZE = libtorrent::sha1_hash::size * 1.6;
const int SHA1_HEX_SIZE = BitTorrent::InfoHash::length() * 2;
const int SHA1_BASE32_SIZE = BitTorrent::InfoHash::length() * 1.6;
return ((((string.size() == SHA1_HEX_SIZE))
&& !string.contains(QRegularExpression(QLatin1String("[^0-9A-Fa-f]"))))
@ -75,7 +77,7 @@ MagnetUri::MagnetUri(const QString &source) @@ -75,7 +77,7 @@ MagnetUri::MagnetUri(const QString &source)
m_name = QString::fromStdString(m_addTorrentParams.name);
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)
m_urlSeeds.append(QUrl(QString::fromStdString(urlSeed)));

53
src/base/bittorrent/peerinfo.cpp

@ -60,17 +60,17 @@ PeerInfo::PeerInfo(const TorrentHandle *torrent, const libt::peer_info &nativeIn @@ -60,17 +60,17 @@ PeerInfo::PeerInfo(const TorrentHandle *torrent, const libt::peer_info &nativeIn
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
{
return (m_nativeInfo.source & libt::peer_info::pex);
return static_cast<bool>(m_nativeInfo.source & libt::peer_info::pex);
}
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
@ -82,102 +82,102 @@ QString PeerInfo::country() const @@ -82,102 +82,102 @@ QString PeerInfo::country() 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
{
return (m_nativeInfo.flags & libt::peer_info::choked);
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::choked);
}
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
{
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
{
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
{
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
{
return (m_nativeInfo.flags & libt::peer_info::handshake);
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::handshake);
}
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
{
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
{
return (m_nativeInfo.flags & libt::peer_info::seed);
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::seed);
}
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
{
return (m_nativeInfo.flags & libt::peer_info::snubbed);
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::snubbed);
}
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
{
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
{
return (m_nativeInfo.flags & libt::peer_info::holepunched);
return static_cast<bool>(m_nativeInfo.flags & libt::peer_info::holepunched);
}
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
{
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
{
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
{
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
{
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
@ -220,8 +220,9 @@ QBitArray PeerInfo::pieces() const @@ -220,8 +220,9 @@ QBitArray PeerInfo::pieces() const
{
QBitArray result(m_nativeInfo.pieces.size());
for (int i = 0; i < m_nativeInfo.pieces.size(); ++i)
result.setBit(i, m_nativeInfo.pieces.get_bit(i));
int i = 0;
for (const bool bit : m_nativeInfo.pieces)
result.setBit(i++, bit);
return result;
}
@ -397,5 +398,5 @@ QString PeerInfo::flagsDescription() const @@ -397,5 +398,5 @@ QString PeerInfo::flagsDescription() 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

@ -0,0 +1,81 @@ @@ -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

@ -0,0 +1,114 @@ @@ -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

@ -0,0 +1,65 @@ @@ -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;
};

61
src/base/bittorrent/session.cpp

@ -62,13 +62,13 @@ @@ -62,13 +62,13 @@
#include <libtorrent/session_stats.hpp>
#include <libtorrent/session_status.hpp>
#include <libtorrent/torrent_info.hpp>
#include <libtorrent/version.hpp>
#include "base/algorithm.h"
#include "base/exceptions.h"
#include "base/global.h"
#include "base/logger.h"
#include "base/net/downloadmanager.h"
#include "base/net/portforwarder.h"
#include "base/net/proxyconfigurationmanager.h"
#include "base/profile.h"
#include "base/torrentfileguard.h"
@ -82,6 +82,7 @@ @@ -82,6 +82,7 @@
#include "magneturi.h"
#include "private/bandwidthscheduler.h"
#include "private/filterparserthread.h"
#include "private/portforwarderimpl.h"
#include "private/resumedatasavingmanager.h"
#include "private/statistics.h"
#include "torrenthandle.h"
@ -106,6 +107,16 @@ using namespace BitTorrent; @@ -106,6 +107,16 @@ using namespace BitTorrent;
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 loadTorrentResumeData(const QByteArray &data, CreateTorrentParams &torrentParams, int &prio, MagnetUri &magnetUri);
@ -134,13 +145,19 @@ namespace @@ -134,13 +145,19 @@ namespace
return result;
}
template <typename LTStr>
QString fromLTString(const LTStr &str)
{
return QString::fromUtf8(str.data(), static_cast<int>(str.size()));
}
template <typename Entry>
QSet<QString> entryListToSetImpl(const Entry &entry)
{
Q_ASSERT(entry.type() == Entry::list_t);
QSet<QString> output;
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))
output.insert(tag);
else
@ -405,7 +422,7 @@ Session::Session(QObject *parent) @@ -405,7 +422,7 @@ Session::Session(QObject *parent)
pack.set_bool(libt::settings_pack::upnp_ignore_nonrouters, true);
configure(pack);
m_nativeSession = new libt::session(pack, 0);
m_nativeSession = new lt::session {pack, LTSessionFlags {0}};
m_nativeSession->set_alert_notify([this]()
{
QMetaObject::invokeMethod(this, "readAlerts", Qt::QueuedConnection);
@ -490,7 +507,7 @@ Session::Session(QObject *parent) @@ -490,7 +507,7 @@ Session::Session(QObject *parent)
}
// initialize PortForwarder instance
Net::PortForwarder::initInstance(m_nativeSession);
new PortForwarderImpl {m_nativeSession};
initMetrics();
m_statsUpdateTimer.start();
@ -936,7 +953,7 @@ Session::~Session() @@ -936,7 +953,7 @@ Session::~Session()
// We must delete PortForwarderImpl before
// we delete libtorrent::session
Net::PortForwarder::freeInstance();
delete Net::PortForwarder::instance();
qDebug("Deleting the session");
delete m_nativeSession;
@ -1665,7 +1682,7 @@ bool Session::cancelLoadMetadata(const InfoHash &hash) @@ -1665,7 +1682,7 @@ bool Session::cancelLoadMetadata(const InfoHash &hash)
const libt::torrent_handle torrent = m_nativeSession->find_torrent(hash);
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...
--m_extraLimit;
adjustLimits();
@ -1930,11 +1947,21 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne @@ -1930,11 +1947,21 @@ bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magne
if (!fromMagnetUri) {
if (params.restored) {
// 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;
}
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) @@ -3966,7 +3993,11 @@ void Session::handlePortmapAlert(const libt::portmap_alert *p)
void Session::handlePeerBlockedAlert(const libt::peer_blocked_alert *p)
{
boost::system::error_code ec;
#if LIBTORRENT_VERSION_NUM < 10200
const std::string ip = p->ip.to_string(ec);
#else
const std::string ip = p->endpoint.address().to_string(ec);
#endif
QString reason;
switch (p->reason) {
case libt::peer_blocked_alert::ip_filter:
@ -4182,31 +4213,31 @@ namespace @@ -4182,31 +4213,31 @@ namespace
if (ec || (fast.type() != libt::bdecode_node::dict_t)) return false;
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())
torrentParams.ratioLimit = fast.dict_find_int_value("qBt-ratioLimit", TorrentHandle::USE_GLOBAL_RATIO * 1000) / 1000.0;
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);
// **************************************************************************************
// Workaround to convert legacy label to category
// 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())
// **************************************************************************************
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.
const auto tagsEntry = fast.dict_find_list("qBt-tags");
if (isList(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.disableTempPath = fast.dict_find_int_value("qBt-tempPathDisabled");
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 isPaused = fast.dict_find_int_value("paused");
torrentParams.paused = fast.dict_find_int_value("qBt-paused", (isPaused && !isAutoManaged));

44
src/base/bittorrent/session.h

@ -47,54 +47,12 @@ @@ -47,54 +47,12 @@
#include "base/settingvalue.h"
#include "base/tristatebool.h"
#include "base/types.h"
#include "private/libtorrentfwd.h"
#include "addtorrentparams.h"
#include "cachestatus.h"
#include "sessionstatus.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 QTimer;
class QStringList;

11
src/base/bittorrent/torrentcreatorthread.cpp

@ -34,6 +34,7 @@ @@ -34,6 +34,7 @@
#include <libtorrent/create_torrent.hpp>
#include <libtorrent/storage.hpp>
#include <libtorrent/torrent_info.hpp>
#include <libtorrent/version.hpp>
#include <QDirIterator>
#include <QFile>
@ -47,6 +48,12 @@ @@ -47,6 +48,12 @@
namespace
{
#if (LIBTORRENT_VERSION_NUM < 10200)
using CreateFlags = int;
#else
using CreateFlags = lt::create_flags_t;
#endif
// do not include files and folders whose
// name starts with a .
bool fileFilter(const std::string &f)
@ -131,7 +138,7 @@ void TorrentCreatorThread::run() @@ -131,7 +138,7 @@ void TorrentCreatorThread::run()
if (isInterruptionRequested()) return;
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
for (QString seed : asConst(m_params.urlSeeds)) {
@ -203,5 +210,5 @@ int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const i @@ -203,5 +210,5 @@ int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const i
libt::add_files(fs, Utils::Fs::toNativePath(inputPath).toStdString(), fileFilter);
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();
}

93
src/base/bittorrent/torrenthandle.cpp

@ -43,6 +43,7 @@ @@ -43,6 +43,7 @@
#include <libtorrent/entry.hpp>
#include <libtorrent/magnet_uri.hpp>
#include <libtorrent/time.hpp>
#include <libtorrent/version.hpp>
#include <QBitArray>
#include <QDateTime>
@ -69,6 +70,28 @@ using namespace BitTorrent; @@ -69,6 +70,28 @@ using namespace BitTorrent;
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;
ListType setToEntryList(const QSet<QString> &input)
@ -635,11 +658,21 @@ QStringList TorrentHandle::absoluteFilePathsUnwanted() const @@ -635,11 +658,21 @@ QStringList TorrentHandle::absoluteFilePathsUnwanted() const
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
@ -838,18 +871,22 @@ bool TorrentHandle::hasError() const @@ -838,18 +871,22 @@ bool TorrentHandle::hasError() const
bool TorrentHandle::hasFilteredPieces() const
{
const std::vector<int> pp = m_nativeHandle.piece_priorities();
return std::any_of(pp.cbegin(), pp.cend(), [](const int priority)
#if (LIBTORRENT_VERSION_NUM < 10200)
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
{
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
@ -1244,7 +1281,7 @@ void TorrentHandle::setFirstLastPiecePriority(const bool enabled) @@ -1244,7 +1281,7 @@ void TorrentHandle::setFirstLastPiecePriority(const bool 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
@ -1253,17 +1290,24 @@ void TorrentHandle::setFirstLastPiecePriorityImpl(const bool enabled, const QVec @@ -1253,17 +1290,24 @@ void TorrentHandle::setFirstLastPiecePriorityImpl(const bool enabled, const QVec
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
// 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) {
const int filePrio = filePriorities[index];
if (filePrio <= 0)
const LTDownloadPriority filePrio = filePriorities[index];
if (filePrio <= LTDownloadPriority {0})
continue;
// 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);
// 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) @@ -1349,8 +1393,11 @@ void TorrentHandle::renameFile(int index, const QString &name)
bool TorrentHandle::saveTorrentFile(const QString &path)
{
if (!m_torrentInfo.isValid()) return false;
#if (LIBTORRENT_VERSION_NUM < 10200)
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();
QVector<char> out;
@ -1572,7 +1619,7 @@ void TorrentHandle::handleSaveResumeDataAlert(const libtorrent::save_resume_data @@ -1572,7 +1619,7 @@ void TorrentHandle::handleSaveResumeDataAlert(const libtorrent::save_resume_data
resumeData["qBt-name"] = m_name.toStdString();
resumeData["qBt-seedStatus"] = m_hasSeedStatus;
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;
m_session->handleTorrentResumeDataReady(this, resumeData);
@ -1916,7 +1963,7 @@ QString TorrentHandle::toMagnetUri() const @@ -1916,7 +1963,7 @@ QString TorrentHandle::toMagnetUri() const
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 (priorities.size() != filesCount()) return;
@ -1927,23 +1974,25 @@ void TorrentHandle::prioritizeFiles(const QVector<int> &priorities) @@ -1927,23 +1974,25 @@ void TorrentHandle::prioritizeFiles(const QVector<int> &priorities)
// Reset 'm_hasSeedStatus' if needed in order to react again to
// 'torrent_finished_alert' and eg show tray notifications
const QVector<qreal> progress = filesProgress();
const QVector<int> oldPriorities = filePriorities();
const QVector<DownloadPriority> oldPriorities = filePriorities();
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;
break;
}
}
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...";
const QString spath = savePath(true);
for (int i = 0; i < priorities.size(); ++i) {
const QString filepath = filePath(i);
// 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 parentAbsPath = Utils::Fs::branchPath(oldAbsPath);
// Make sure the file does not already exists
@ -1976,7 +2025,7 @@ void TorrentHandle::prioritizeFiles(const QVector<int> &priorities) @@ -1976,7 +2025,7 @@ void TorrentHandle::prioritizeFiles(const QVector<int> &priorities)
}
// Move wanted files back to their original folder
if (priorities[i] > 0) {
if (priorities[i] > DownloadPriority::Ignored) {
const QString parentRelPath = Utils::Fs::branchPath(filepath);
if (QDir(parentRelPath).dirName() == ".unwanted") {
const QString oldName = Utils::Fs::fileName(filepath);

33
src/base/bittorrent/torrenthandle.h

@ -42,7 +42,9 @@ @@ -42,7 +42,9 @@
#include <QString>
#include <QVector>
#include "private/libtorrentfwd.h"
#include "private/speedmonitor.h"
#include "downloadpriority.h"
#include "infohash.h"
#include "torrentinfo.h"
@ -53,29 +55,6 @@ class QDateTime; @@ -53,29 +55,6 @@ class QDateTime;
class QStringList;
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
{
class PeerInfo;
@ -103,7 +82,7 @@ namespace BitTorrent @@ -103,7 +82,7 @@ namespace BitTorrent
int uploadLimit;
int downloadLimit;
// for new torrents
QVector<int> filePriorities;
QVector<DownloadPriority> filePriorities;
// for restored torrents
qreal ratioLimit;
int seedingTimeLimit;
@ -258,7 +237,7 @@ namespace BitTorrent @@ -258,7 +237,7 @@ namespace BitTorrent
qlonglong fileSize(int index) const;
QStringList absoluteFilePaths() const;
QStringList absoluteFilePathsUnwanted() const;
QVector<int> filePriorities() const;
QVector<DownloadPriority> filePriorities() const;
TorrentInfo info() const;
bool isSeed() const;
@ -337,7 +316,7 @@ namespace BitTorrent @@ -337,7 +316,7 @@ namespace BitTorrent
void forceRecheck();
void renameFile(int index, const QString &name);
bool saveTorrentFile(const QString &path);
void prioritizeFiles(const QVector<int> &priorities);
void prioritizeFiles(const QVector<DownloadPriority> &priorities);
void setRatioLimit(qreal limit);
void setSeedingTimeLimit(int limit);
void setUploadLimit(int limit);
@ -410,7 +389,7 @@ namespace BitTorrent @@ -410,7 +389,7 @@ namespace BitTorrent
bool addTracker(const TrackerEntry &tracker);
bool addUrlSeed(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;
libtorrent::torrent_handle m_nativeHandle;

39
src/base/bittorrent/torrentinfo.cpp

@ -28,6 +28,7 @@ @@ -28,6 +28,7 @@
#include "torrentinfo.h"
#include <boost/optional.hpp>
#include <libtorrent/error_code.hpp>
#include <QByteArray>
@ -42,12 +43,27 @@ @@ -42,12 +43,27 @@
#include "infohash.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;
using namespace BitTorrent;
TorrentInfo::TorrentInfo(NativeConstPtr nativeInfo)
{
#if (LIBTORRENT_VERSION_NUM < 10200)
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)
@ -190,7 +206,7 @@ int TorrentInfo::pieceLength() const @@ -190,7 +206,7 @@ int TorrentInfo::pieceLength() const
int TorrentInfo::pieceLength(const int index) const
{
if (!isValid()) return -1;
return m_nativeInfo->piece_size(index);
return m_nativeInfo->piece_size(LTPieceIndex {index});
}
int TorrentInfo::piecesCount() const
@ -202,7 +218,8 @@ int TorrentInfo::piecesCount() const @@ -202,7 +218,8 @@ int TorrentInfo::piecesCount() const
QString TorrentInfo::filePath(const int index) const
{
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
@ -222,19 +239,20 @@ QString TorrentInfo::fileName(const int index) const @@ -222,19 +239,20 @@ QString TorrentInfo::fileName(const int index) const
QString TorrentInfo::origFilePath(const int index) const
{
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
{
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
{
if (!isValid()) return -1;
return m_nativeInfo->files().file_offset(index);
return m_nativeInfo->files().file_offset(LTFileIndex {index});
}
QList<TrackerEntry> TorrentInfo::trackers() const
@ -285,11 +303,12 @@ QVector<int> TorrentInfo::fileIndicesForPiece(const int pieceIndex) const @@ -285,11 +303,12 @@ QVector<int> TorrentInfo::fileIndicesForPiece(const int pieceIndex) const
return {};
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;
res.reserve(int(files.size()));
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;
}
@ -304,7 +323,7 @@ QVector<QByteArray> TorrentInfo::pieceHashes() const @@ -304,7 +323,7 @@ QVector<QByteArray> TorrentInfo::pieceHashes() const
hashes.reserve(count);
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;
}
@ -333,8 +352,8 @@ TorrentInfo::PieceRange TorrentInfo::filePieces(const int fileIndex) const @@ -333,8 +352,8 @@ TorrentInfo::PieceRange TorrentInfo::filePieces(const int fileIndex) const
}
const libt::file_storage &files = nativeInfo()->files();
const auto fileSize = files.file_size(fileIndex);
const auto fileOffset = files.file_offset(fileIndex);
const auto fileSize = files.file_size(LTFileIndex {fileIndex});
const auto fileOffset = files.file_offset(LTFileIndex {fileIndex});
return makeInterval(static_cast<int>(fileOffset / pieceLength()),
static_cast<int>((fileOffset + fileSize - 1) / pieceLength()));
}

11
src/base/bittorrent/torrentinfo.h

@ -30,12 +30,14 @@ @@ -30,12 +30,14 @@
#define BITTORRENT_TORRENTINFO_H
#include <libtorrent/torrent_info.hpp>
#include <libtorrent/version.hpp>
#include <QCoreApplication>
#include <QList>
#include <QVector>
#include "base/indexrange.h"
#include "private/libtorrentfwd.h"
class QByteArray;
class QDateTime;
@ -53,8 +55,13 @@ namespace BitTorrent @@ -53,8 +55,13 @@ namespace BitTorrent
Q_DECLARE_TR_FUNCTIONS(TorrentInfo)
public:
typedef boost::shared_ptr<const libtorrent::torrent_info> NativeConstPtr;
typedef boost::shared_ptr<libtorrent::torrent_info> NativePtr;
#if (LIBTORRENT_VERSION_NUM < 10200)
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 = {});
TorrentInfo(const TorrentInfo &other);

49
src/base/bittorrent/trackerentry.cpp

@ -28,6 +28,10 @@ @@ -28,6 +28,10 @@
#include "trackerentry.h"
#include <algorithm>
#include <libtorrent/version.hpp>
#include <QString>
#include <QUrl>
@ -48,6 +52,19 @@ QString TrackerEntry::url() const @@ -48,6 +52,19 @@ QString TrackerEntry::url() const
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
{
return m_nativeEntry.tier;
@ -57,7 +74,7 @@ TrackerEntry::Status TrackerEntry::status() const @@ -57,7 +74,7 @@ TrackerEntry::Status TrackerEntry::status() const
{
// libtorrent::announce_entry::is_working() returns
// true when the tracker hasn't been tried yet.
if (m_nativeEntry.verified && m_nativeEntry.is_working())
if (m_nativeEntry.verified && isWorking())
return Working;
if ((m_nativeEntry.fails == 0) && m_nativeEntry.updating)
return Updating;
@ -72,6 +89,36 @@ void TrackerEntry::setTier(const int value) @@ -72,6 +89,36 @@ void TrackerEntry::setTier(const int 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
{
return m_nativeEntry;

5
src/base/bittorrent/trackerentry.h

@ -53,11 +53,16 @@ namespace BitTorrent @@ -53,11 +53,16 @@ namespace BitTorrent
TrackerEntry &operator=(const TrackerEntry &other) = default;
QString url() const;
bool isWorking() const;
Status status() const;
int tier() const;
void setTier(int value);
int numSeeds() const;
int numLeeches() const;
int numDownloaded() const;
libtorrent::announce_entry nativeEntry() const;
private:

103
src/base/net/portforwarder.cpp

@ -28,110 +28,21 @@ @@ -28,110 +28,21 @@
#include "portforwarder.h"
#include <QDebug>
#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())
start();
}
PortForwarder::~PortForwarder()
Net::PortForwarder::PortForwarder(QObject *parent)
: QObject {parent}
{
stop();
Q_ASSERT(!m_instance);
m_instance = this;
}
void PortForwarder::initInstance(libtorrent::session *const provider)
Net::PortForwarder::~PortForwarder()
{
if (!m_instance)
m_instance = new PortForwarder(provider);
}
void PortForwarder::freeInstance()
{
if (m_instance) {
delete m_instance;
m_instance = nullptr;
}
}
PortForwarder *PortForwarder::instance()
Net::PortForwarder *Net::PortForwarder::instance()
{
return m_instance;
}
bool PortForwarder::isEnabled() const
{
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;
Net::PortForwarder *Net::PortForwarder::m_instance = nullptr;

30
src/base/net/portforwarder.h

@ -29,43 +29,27 @@ @@ -29,43 +29,27 @@
#ifndef NET_PORTFORWARDER_H
#define NET_PORTFORWARDER_H
#include <QHash>
#include <QObject>
namespace libtorrent
{
class session;
}
namespace Net
{
class PortForwarder : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(PortForwarder)
public:
static void initInstance(libtorrent::session *const provider);
static void freeInstance();
explicit PortForwarder(QObject *parent = nullptr);
~PortForwarder() override;
static PortForwarder *instance();
bool isEnabled() const;
void setEnabled(bool enabled);
virtual bool isEnabled() const = 0;
virtual void setEnabled(bool enabled) = 0;
void addPort(quint16 port);
void deletePort(quint16 port);
virtual void addPort(quint16 port) = 0;
virtual void deletePort(quint16 port) = 0;
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;
};
}

14
src/gui/addnewtorrentdialog.cpp

@ -37,7 +37,7 @@ @@ -37,7 +37,7 @@
#include <QUrl>
#include <QVector>
#include "base/bittorrent/filepriority.h"
#include "base/bittorrent/downloadpriority.h"
#include "base/bittorrent/magneturi.h"
#include "base/bittorrent/session.h"
#include "base/bittorrent/torrenthandle.h"
@ -420,10 +420,10 @@ void AddNewTorrentDialog::updateDiskSpaceLabel() @@ -420,10 +420,10 @@ void AddNewTorrentDialog::updateDiskSpaceLabel()
if (m_hasMetadata) {
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());
for (int i = 0; i < priorities.size(); ++i)
if (priorities[i] > 0)
if (priorities[i] > BitTorrent::DownloadPriority::Ignored)
torrentSize += m_torrentInfo.fileSize(i);
}
else {
@ -612,13 +612,13 @@ void AddNewTorrentDialog::displayContentTreeMenu(const QPoint &) @@ -612,13 +612,13 @@ void AddNewTorrentDialog::displayContentTreeMenu(const QPoint &)
renameSelectedFile();
}
else {
BitTorrent::FilePriority prio = BitTorrent::FilePriority::Normal;
BitTorrent::DownloadPriority prio = BitTorrent::DownloadPriority::Normal;
if (act == m_ui->actionHigh)
prio = BitTorrent::FilePriority::High;
prio = BitTorrent::DownloadPriority::High;
else if (act == m_ui->actionMaximum)
prio = BitTorrent::FilePriority::Maximum;
prio = BitTorrent::DownloadPriority::Maximum;
else if (act == m_ui->actionNotDownloaded)
prio = BitTorrent::FilePriority::Ignored;
prio = BitTorrent::DownloadPriority::Ignored;
qDebug("Setting files priority");
for (const QModelIndex &index : selectedRows) {

16
src/gui/properties/propertieswidget.cpp

@ -39,7 +39,7 @@ @@ -39,7 +39,7 @@
#include <QThread>
#include <QUrl>
#include "base/bittorrent/filepriority.h"
#include "base/bittorrent/downloadpriority.h"
#include "base/bittorrent/session.h"
#include "base/preferences.h"
#include "base/unicodestrings.h"
@ -621,13 +621,13 @@ void PropertiesWidget::displayFilesListMenu(const QPoint &) @@ -621,13 +621,13 @@ void PropertiesWidget::displayFilesListMenu(const QPoint &)
renameSelectedFile();
}
else {
BitTorrent::FilePriority prio = BitTorrent::FilePriority::Normal;
BitTorrent::DownloadPriority prio = BitTorrent::DownloadPriority::Normal;
if (act == m_ui->actionHigh)
prio = BitTorrent::FilePriority::High;
prio = BitTorrent::DownloadPriority::High;
else if (act == m_ui->actionMaximum)
prio = BitTorrent::FilePriority::Maximum;
prio = BitTorrent::DownloadPriority::Maximum;
else if (act == m_ui->actionNotDownloaded)
prio = BitTorrent::FilePriority::Ignored;
prio = BitTorrent::DownloadPriority::Ignored;
qDebug("Setting files priority");
for (const QModelIndex &index : selectedRows) {
@ -894,11 +894,7 @@ void PropertiesWidget::editWebSeed() @@ -894,11 +894,7 @@ void PropertiesWidget::editWebSeed()
void PropertiesWidget::applyPriorities()
{
qDebug("Saving files priorities");
const QVector<int> priorities = m_propListModel->model()->getFilePriorities();
// Prioritize the files
qDebug("prioritize files: %d", priorities[0]);
m_torrent->prioritizeFiles(priorities);
m_torrent->prioritizeFiles(m_propListModel->model()->getFilePriorities());
}
void PropertiesWidget::filteredFilesChanged()

32
src/gui/properties/proplistdelegate.cpp

@ -40,7 +40,7 @@ @@ -40,7 +40,7 @@
#include <QProxyStyle>
#endif
#include "base/bittorrent/filepriority.h"
#include "base/bittorrent/downloadpriority.h"
#include "base/unicodestrings.h"
#include "base/utils/misc.h"
#include "base/utils/string.h"
@ -93,7 +93,7 @@ void PropListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti @@ -93,7 +93,7 @@ void PropListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
newopt.maximum = 100;
newopt.minimum = 0;
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.palette = progressBarDisabledPalette();
}
@ -111,17 +111,17 @@ void PropListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti @@ -111,17 +111,17 @@ void PropListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
break;
case PRIORITY: {
QString text = "";
switch (static_cast<BitTorrent::FilePriority>(index.data().toInt())) {
case BitTorrent::FilePriority::Mixed:
switch (static_cast<BitTorrent::DownloadPriority>(index.data().toInt())) {
case BitTorrent::DownloadPriority::Mixed:
text = tr("Mixed", "Mixed (priorities");
break;
case BitTorrent::FilePriority::Ignored:
case BitTorrent::DownloadPriority::Ignored:
text = tr("Not downloaded");
break;
case BitTorrent::FilePriority::High:
case BitTorrent::DownloadPriority::High:
text = tr("High", "High (priority)");
break;
case BitTorrent::FilePriority::Maximum:
case BitTorrent::DownloadPriority::Maximum:
text = tr("Maximum", "Maximum (priority)");
break;
default:
@ -155,14 +155,14 @@ void PropListDelegate::setEditorData(QWidget *editor, const QModelIndex &index) @@ -155,14 +155,14 @@ void PropListDelegate::setEditorData(QWidget *editor, const QModelIndex &index)
{
auto *combobox = static_cast<QComboBox *>(editor);
// Set combobox index
switch (static_cast<BitTorrent::FilePriority>(index.data().toInt())) {
case BitTorrent::FilePriority::Ignored:
switch (static_cast<BitTorrent::DownloadPriority>(index.data().toInt())) {
case BitTorrent::DownloadPriority::Ignored:
combobox->setCurrentIndex(0);
break;
case BitTorrent::FilePriority::High:
case BitTorrent::DownloadPriority::High:
combobox->setCurrentIndex(2);
break;
case BitTorrent::FilePriority::Maximum:
case BitTorrent::DownloadPriority::Maximum:
combobox->setCurrentIndex(3);
break;
default:
@ -181,7 +181,7 @@ QWidget *PropListDelegate::createEditor(QWidget *parent, const QStyleOptionViewI @@ -181,7 +181,7 @@ QWidget *PropListDelegate::createEditor(QWidget *parent, const QStyleOptionViewI
return nullptr;
}
if (index.data().toInt() == static_cast<int>(BitTorrent::FilePriority::Mixed))
if (index.data().toInt() == static_cast<int>(BitTorrent::DownloadPriority::Mixed))
return nullptr;
auto *editor = new QComboBox(parent);
@ -199,16 +199,16 @@ void PropListDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, @@ -199,16 +199,16 @@ void PropListDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
int value = combobox->currentIndex();
qDebug("PropListDelegate: setModelData(%d)", value);
BitTorrent::FilePriority prio = BitTorrent::FilePriority::Normal; // NORMAL
BitTorrent::DownloadPriority prio = BitTorrent::DownloadPriority::Normal; // NORMAL
switch (value) {
case 0:
prio = BitTorrent::FilePriority::Ignored; // IGNORED
prio = BitTorrent::DownloadPriority::Ignored; // IGNORED
break;
case 2:
prio = BitTorrent::FilePriority::High; // HIGH
prio = BitTorrent::DownloadPriority::High; // HIGH
break;
case 3:
prio = BitTorrent::FilePriority::Maximum; // MAX
prio = BitTorrent::DownloadPriority::Maximum; // MAX
break;
}

6
src/gui/properties/trackerlistwidget.cpp

@ -367,9 +367,9 @@ void TrackerListWidget::loadTrackers() @@ -367,9 +367,9 @@ void TrackerListWidget::loadTrackers()
}
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_LEECHES, (entry.nativeEntry().scrape_incomplete > -1) ? QString::number(entry.nativeEntry().scrape_incomplete) : tr("N/A"));
item->setText(COL_DOWNLOADED, (entry.nativeEntry().scrape_downloaded > -1) ? QString::number(entry.nativeEntry().scrape_downloaded) : tr("N/A"));
item->setText(COL_SEEDS, (entry.numSeeds() > -1) ? QString::number(entry.numSeeds()) : tr("N/A"));
item->setText(COL_LEECHES, (entry.numLeeches() > -1) ? QString::number(entry.numLeeches()) : 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_PEERS, (Qt::AlignRight | Qt::AlignVCenter));

32
src/gui/torrentcontentmodel.cpp

@ -50,7 +50,7 @@ @@ -50,7 +50,7 @@
#include <QPixmapCache>
#endif
#include "base/bittorrent/filepriority.h"
#include "base/bittorrent/downloadpriority.h"
#include "base/global.h"
#include "base/utils/misc.h"
#include "base/utils/fs.h"
@ -239,7 +239,7 @@ void TorrentContentModel::updateFilesProgress(const QVector<qreal> &fp) @@ -239,7 +239,7 @@ void TorrentContentModel::updateFilesProgress(const QVector<qreal> &fp)
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());
// XXX: Why is this necessary?
@ -248,7 +248,7 @@ void TorrentContentModel::updateFilesPriorities(const QVector<int> &fprio) @@ -248,7 +248,7 @@ void TorrentContentModel::updateFilesPriorities(const QVector<int> &fprio)
emit layoutAboutToBeChanged();
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()));
}
@ -266,12 +266,12 @@ void TorrentContentModel::updateFilesAvailability(const QVector<qreal> &fa) @@ -266,12 +266,12 @@ void TorrentContentModel::updateFilesAvailability(const QVector<qreal> &fa)
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());
for (const TorrentContentModelFile *file : asConst(m_filesIndex))
prio.push_back(static_cast<int>(file->priority()));
prio.push_back(file->priority());
return prio;
}
@ -279,7 +279,7 @@ bool TorrentContentModel::allFiltered() const @@ -279,7 +279,7 @@ bool TorrentContentModel::allFiltered() const
{
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 @@ -300,11 +300,11 @@ bool TorrentContentModel::setData(const QModelIndex &index, const QVariant &valu
auto *item = static_cast<TorrentContentModelItem*>(index.internalPointer());
qDebug("setData(%s, %d", qUtf8Printable(item->name()), 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)
prio = BitTorrent::FilePriority::Mixed;
prio = BitTorrent::DownloadPriority::Mixed;
else if (value.toInt() == Qt::Unchecked)
prio = BitTorrent::FilePriority::Ignored;
prio = BitTorrent::DownloadPriority::Ignored;
item->setPriority(prio);
// Update folders progress in the tree
@ -324,7 +324,7 @@ bool TorrentContentModel::setData(const QModelIndex &index, const QVariant &valu @@ -324,7 +324,7 @@ bool TorrentContentModel::setData(const QModelIndex &index, const QVariant &valu
item->setName(value.toString());
break;
case TorrentContentModelItem::COL_PRIO:
item->setPriority(static_cast<BitTorrent::FilePriority>(value.toInt()));
item->setPriority(static_cast<BitTorrent::DownloadPriority>(value.toInt()));
break;
default:
return false;
@ -366,9 +366,9 @@ QVariant TorrentContentModel::data(const QModelIndex &index, int role) const @@ -366,9 +366,9 @@ QVariant TorrentContentModel::data(const QModelIndex &index, int role) const
}
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;
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::Checked;
}
@ -503,8 +503,8 @@ void TorrentContentModel::selectAll() @@ -503,8 +503,8 @@ void TorrentContentModel::selectAll()
{
for (int i = 0; i < m_rootItem->childCount(); ++i) {
TorrentContentModelItem* child = m_rootItem->child(i);
if (child->priority() == BitTorrent::FilePriority::Ignored)
child->setPriority(BitTorrent::FilePriority::Normal);
if (child->priority() == BitTorrent::DownloadPriority::Ignored)
child->setPriority(BitTorrent::DownloadPriority::Normal);
}
emit dataChanged(index(0, 0), index(rowCount(), columnCount()));
}
@ -512,6 +512,6 @@ void TorrentContentModel::selectAll() @@ -512,6 +512,6 @@ void TorrentContentModel::selectAll()
void TorrentContentModel::selectNone()
{
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()));
}

5
src/gui/torrentcontentmodel.h

@ -43,15 +43,16 @@ class TorrentContentModelFile; @@ -43,15 +43,16 @@ class TorrentContentModelFile;
class TorrentContentModel : public QAbstractItemModel
{
Q_OBJECT
Q_DISABLE_COPY(TorrentContentModel)
public:
TorrentContentModel(QObject *parent = nullptr);
~TorrentContentModel() override;
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);
QVector<int> getFilePriorities() const;
QVector<BitTorrent::DownloadPriority> getFilePriorities() const;
bool allFiltered() const;
int columnCount(const QModelIndex &parent = {}) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;

4
src/gui/torrentcontentmodelfile.cpp

@ -52,9 +52,9 @@ int TorrentContentModelFile::fileIndex() const @@ -52,9 +52,9 @@ int TorrentContentModelFile::fileIndex() const
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)
return;

4
src/gui/torrentcontentmodelfile.h

@ -29,7 +29,7 @@ @@ -29,7 +29,7 @@
#ifndef TORRENTCONTENTMODELFILE_H
#define TORRENTCONTENTMODELFILE_H
#include "base/bittorrent/filepriority.h"
#include "base/bittorrent/downloadpriority.h"
#include "torrentcontentmodelitem.h"
class TorrentContentModelFile : public TorrentContentModelItem
@ -39,7 +39,7 @@ public: @@ -39,7 +39,7 @@ public:
TorrentContentModelFolder *parent, int fileIndex);
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 setAvailability(qreal availability);
ItemType itemType() const override;

12
src/gui/torrentcontentmodelfolder.cpp

@ -109,10 +109,10 @@ void TorrentContentModelFolder::updatePriority() @@ -109,10 +109,10 @@ void TorrentContentModelFolder::updatePriority()
// If all children have the same priority
// then the folder should have the same
// 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) {
if (m_childItems.at(i)->priority() != prio) {
setPriority(BitTorrent::FilePriority::Mixed);
setPriority(BitTorrent::DownloadPriority::Mixed);
return;
}
}
@ -121,7 +121,7 @@ void TorrentContentModelFolder::updatePriority() @@ -121,7 +121,7 @@ void TorrentContentModelFolder::updatePriority()
setPriority(prio);
}
void TorrentContentModelFolder::setPriority(BitTorrent::FilePriority newPriority, bool updateParent)
void TorrentContentModelFolder::setPriority(BitTorrent::DownloadPriority newPriority, bool updateParent)
{
if (m_priority == newPriority)
return;
@ -133,7 +133,7 @@ void TorrentContentModelFolder::setPriority(BitTorrent::FilePriority newPriority @@ -133,7 +133,7 @@ void TorrentContentModelFolder::setPriority(BitTorrent::FilePriority newPriority
m_parentItem->updatePriority();
// Update children
if (m_priority != BitTorrent::FilePriority::Mixed)
if (m_priority != BitTorrent::DownloadPriority::Mixed)
for (TorrentContentModelItem *child : asConst(m_childItems))
child->setPriority(m_priority, false);
}
@ -144,7 +144,7 @@ void TorrentContentModelFolder::recalculateProgress() @@ -144,7 +144,7 @@ void TorrentContentModelFolder::recalculateProgress()
qulonglong tSize = 0;
qulonglong tRemaining = 0;
for (TorrentContentModelItem *child : asConst(m_childItems)) {
if (child->priority() == BitTorrent::FilePriority::Ignored)
if (child->priority() == BitTorrent::DownloadPriority::Ignored)
continue;
if (child->itemType() == FolderType)
@ -167,7 +167,7 @@ void TorrentContentModelFolder::recalculateAvailability() @@ -167,7 +167,7 @@ void TorrentContentModelFolder::recalculateAvailability()
qulonglong tSize = 0;
bool foundAnyData = false;
for (TorrentContentModelItem *child : asConst(m_childItems)) {
if (child->priority() == BitTorrent::FilePriority::Ignored)
if (child->priority() == BitTorrent::DownloadPriority::Ignored)
continue;
if (child->itemType() == FolderType)

4
src/gui/torrentcontentmodelfolder.h

@ -29,7 +29,7 @@ @@ -29,7 +29,7 @@
#ifndef TORRENTCONTENTMODELFOLDER_H
#define TORRENTCONTENTMODELFOLDER_H
#include "base/bittorrent/filepriority.h"
#include "base/bittorrent/downloadpriority.h"
#include "torrentcontentmodelitem.h"
class TorrentContentModelFolder : public TorrentContentModelItem
@ -50,7 +50,7 @@ public: @@ -50,7 +50,7 @@ public:
void recalculateAvailability();
void updatePriority();
void setPriority(BitTorrent::FilePriority newPriority, bool updateParent = true) override;
void setPriority(BitTorrent::DownloadPriority newPriority, bool updateParent = true) override;
void deleteAllChildren();
const QList<TorrentContentModelItem*> &children() const;

4
src/gui/torrentcontentmodelitem.cpp

@ -38,7 +38,7 @@ TorrentContentModelItem::TorrentContentModelItem(TorrentContentModelFolder *pare @@ -38,7 +38,7 @@ TorrentContentModelItem::TorrentContentModelItem(TorrentContentModelFolder *pare
: m_parentItem(parent)
, m_size(0)
, m_remaining(0)
, m_priority(BitTorrent::FilePriority::Normal)
, m_priority(BitTorrent::DownloadPriority::Normal)
, m_progress(0)
, m_availability(-1.)
{
@ -90,7 +90,7 @@ qreal TorrentContentModelItem::availability() const @@ -90,7 +90,7 @@ qreal TorrentContentModelItem::availability() const
return (m_size > 0) ? m_availability : 0;
}
BitTorrent::FilePriority TorrentContentModelItem::priority() const
BitTorrent::DownloadPriority TorrentContentModelItem::priority() const
{
Q_ASSERT(!isRootItem());
return m_priority;

8
src/gui/torrentcontentmodelitem.h

@ -32,7 +32,7 @@ @@ -32,7 +32,7 @@
#include <QList>
#include <QVariant>
#include "base/bittorrent/filepriority.h"
#include "base/bittorrent/downloadpriority.h"
class TorrentContentModelFolder;
@ -72,8 +72,8 @@ public: @@ -72,8 +72,8 @@ public:
qreal availability() const;
BitTorrent::FilePriority priority() const;
virtual void setPriority(BitTorrent::FilePriority newPriority, bool updateParent = true) = 0;
BitTorrent::DownloadPriority priority() const;
virtual void setPriority(BitTorrent::DownloadPriority newPriority, bool updateParent = true) = 0;
int columnCount() const;
QVariant data(int column) const;
@ -87,7 +87,7 @@ protected: @@ -87,7 +87,7 @@ protected:
QString m_name;
qulonglong m_size;
qulonglong m_remaining;
BitTorrent::FilePriority m_priority;
BitTorrent::DownloadPriority m_priority;
qreal m_progress;
qreal m_availability;
};

2
src/webui/api/serialize/serialize_torrent.cpp

@ -92,7 +92,7 @@ QVariantMap serialize(const BitTorrent::TorrentHandle &torrent) @@ -92,7 +92,7 @@ QVariantMap serialize(const BitTorrent::TorrentHandle &torrent)
ret[KEY_TORRENT_PROGRESS] = torrent.progress();
ret[KEY_TORRENT_DLSPEED] = torrent.downloadPayloadRate();
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_NUM_COMPLETE] = torrent.totalSeedsCount();
ret[KEY_TORRENT_LEECHS] = torrent.leechsCount();

18
src/webui/api/torrentscontroller.cpp

@ -39,7 +39,7 @@ @@ -39,7 +39,7 @@
#include <QRegularExpression>
#include <QUrl>
#include "base/bittorrent/filepriority.h"
#include "base/bittorrent/downloadpriority.h"
#include "base/bittorrent/peerinfo.h"
#include "base/bittorrent/session.h"
#include "base/bittorrent/torrenthandle.h"
@ -393,9 +393,9 @@ void TorrentsController::trackersAction() @@ -393,9 +393,9 @@ void TorrentsController::trackersAction()
{KEY_TRACKER_STATUS, static_cast<int>(tracker.status())},
{KEY_TRACKER_PEERS_COUNT, data.numPeers},
{KEY_TRACKER_MSG, data.lastMessage.trimmed()},
{KEY_TRACKER_SEEDS_COUNT, tracker.nativeEntry().scrape_complete},
{KEY_TRACKER_LEECHES_COUNT, tracker.nativeEntry().scrape_incomplete},
{KEY_TRACKER_DOWNLOADED_COUNT, tracker.nativeEntry().scrape_downloaded}
{KEY_TRACKER_SEEDS_COUNT, tracker.numSeeds()},
{KEY_TRACKER_LEECHES_COUNT, tracker.numLeeches()},
{KEY_TRACKER_DOWNLOADED_COUNT, tracker.numDownloaded()}
};
}
@ -446,14 +446,14 @@ void TorrentsController::filesAction() @@ -446,14 +446,14 @@ void TorrentsController::filesAction()
throw APIError(APIErrorType::NotFound);
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> fileAvailability = torrent->availableFileFractions();
const BitTorrent::TorrentInfo info = torrent->info();
for (int i = 0; i < torrent->filesCount(); ++i) {
QVariantMap fileDict;
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_AVAILABILITY] = fileAvailability[i];
@ -701,11 +701,11 @@ void TorrentsController::filePrioAction() @@ -701,11 +701,11 @@ void TorrentsController::filePrioAction()
const QString hash = params()["hash"];
bool ok = false;
const int priority = params()["priority"].toInt(&ok);
const auto priority = static_cast<BitTorrent::DownloadPriority>(params()["priority"].toInt(&ok));
if (!ok)
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"));
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
@ -715,7 +715,7 @@ void TorrentsController::filePrioAction() @@ -715,7 +715,7 @@ void TorrentsController::filePrioAction()
throw APIError(APIErrorType::Conflict, tr("Torrent's metadata has not yet downloaded"));
const int filesCount = torrent->filesCount();
QVector<int> priorities = torrent->filePriorities();
QVector<BitTorrent::DownloadPriority> priorities = torrent->filePriorities();
bool priorityChanged = false;
for (const QString &fileID : params()["id"].split('|')) {
const int id = fileID.toInt(&ok);

Loading…
Cancel
Save