mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-29 11:48:05 -06:00
committed by
GitHub
parent
773cb1e55d
commit
d5e41bf679
@@ -32,6 +32,7 @@ add_library(qbt_base STATIC
|
||||
bittorrent/session.h
|
||||
bittorrent/sessionimpl.h
|
||||
bittorrent/sessionstatus.h
|
||||
bittorrent/sharelimitaction.h
|
||||
bittorrent/speedmonitor.h
|
||||
bittorrent/sslparameters.h
|
||||
bittorrent/torrent.h
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015-2023 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2015-2024 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
|
||||
@@ -51,6 +51,7 @@ const QString PARAM_UPLOADLIMIT = u"upload_limit"_s;
|
||||
const QString PARAM_DOWNLOADLIMIT = u"download_limit"_s;
|
||||
const QString PARAM_SEEDINGTIMELIMIT = u"seeding_time_limit"_s;
|
||||
const QString PARAM_INACTIVESEEDINGTIMELIMIT = u"inactive_seeding_time_limit"_s;
|
||||
const QString PARAM_SHARELIMITACTION = u"share_limit_action"_s;
|
||||
const QString PARAM_RATIOLIMIT = u"ratio_limit"_s;
|
||||
const QString PARAM_SSL_CERTIFICATE = u"ssl_certificate"_s;
|
||||
const QString PARAM_SSL_PRIVATEKEY = u"ssl_private_key"_s;
|
||||
@@ -96,10 +97,10 @@ namespace
|
||||
}
|
||||
|
||||
template <typename Enum>
|
||||
Enum getEnum(const QJsonObject &jsonObj, const QString &key)
|
||||
Enum getEnum(const QJsonObject &jsonObj, const QString &key, const Enum defaultValue = {})
|
||||
{
|
||||
const QJsonValue jsonVal = jsonObj.value(key);
|
||||
return Utils::String::toEnum<Enum>(jsonVal.toString(), {});
|
||||
return Utils::String::toEnum<Enum>(jsonVal.toString(), defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +128,7 @@ BitTorrent::AddTorrentParams BitTorrent::parseAddTorrentParams(const QJsonObject
|
||||
.seedingTimeLimit = jsonObj.value(PARAM_SEEDINGTIMELIMIT).toInt(Torrent::USE_GLOBAL_SEEDING_TIME),
|
||||
.inactiveSeedingTimeLimit = jsonObj.value(PARAM_INACTIVESEEDINGTIMELIMIT).toInt(Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME),
|
||||
.ratioLimit = jsonObj.value(PARAM_RATIOLIMIT).toDouble(Torrent::USE_GLOBAL_RATIO),
|
||||
.shareLimitAction = getEnum<ShareLimitAction>(jsonObj, PARAM_SHARELIMITACTION, ShareLimitAction::Default),
|
||||
.sslParameters =
|
||||
{
|
||||
.certificate = QSslCertificate(jsonObj.value(PARAM_SSL_CERTIFICATE).toString().toLatin1()),
|
||||
@@ -146,12 +148,13 @@ QJsonObject BitTorrent::serializeAddTorrentParams(const AddTorrentParams ¶ms
|
||||
{PARAM_SAVEPATH, params.savePath.data()},
|
||||
{PARAM_DOWNLOADPATH, params.downloadPath.data()},
|
||||
{PARAM_OPERATINGMODE, Utils::String::fromEnum(params.addForced
|
||||
? TorrentOperatingMode::Forced : TorrentOperatingMode::AutoManaged)},
|
||||
? TorrentOperatingMode::Forced : TorrentOperatingMode::AutoManaged)},
|
||||
{PARAM_SKIPCHECKING, params.skipChecking},
|
||||
{PARAM_UPLOADLIMIT, params.uploadLimit},
|
||||
{PARAM_DOWNLOADLIMIT, params.downloadLimit},
|
||||
{PARAM_SEEDINGTIMELIMIT, params.seedingTimeLimit},
|
||||
{PARAM_INACTIVESEEDINGTIMELIMIT, params.inactiveSeedingTimeLimit},
|
||||
{PARAM_SHARELIMITACTION, Utils::String::fromEnum(params.shareLimitAction)},
|
||||
{PARAM_RATIOLIMIT, params.ratioLimit},
|
||||
{PARAM_SSL_CERTIFICATE, QString::fromLatin1(params.sslParameters.certificate.toPem())},
|
||||
{PARAM_SSL_PRIVATEKEY, QString::fromLatin1(params.sslParameters.privateKey.toPem())},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015-2023 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2015-2024 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
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "base/path.h"
|
||||
#include "base/tagset.h"
|
||||
#include "sharelimitaction.h"
|
||||
#include "sslparameters.h"
|
||||
#include "torrent.h"
|
||||
#include "torrentcontentlayout.h"
|
||||
@@ -70,6 +71,7 @@ namespace BitTorrent
|
||||
int seedingTimeLimit = Torrent::USE_GLOBAL_SEEDING_TIME;
|
||||
int inactiveSeedingTimeLimit = Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME;
|
||||
qreal ratioLimit = Torrent::USE_GLOBAL_RATIO;
|
||||
ShareLimitAction shareLimitAction = ShareLimitAction::Default;
|
||||
SSLParameters sslParameters;
|
||||
|
||||
friend bool operator==(const AddTorrentParams &lhs, const AddTorrentParams &rhs) = default;
|
||||
|
||||
@@ -231,14 +231,16 @@ BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorre
|
||||
torrentParams.firstLastPiecePriority = resumeDataRoot.dict_find_int_value("qBt-firstLastPiecePriority");
|
||||
torrentParams.seedingTimeLimit = resumeDataRoot.dict_find_int_value("qBt-seedingTimeLimit", Torrent::USE_GLOBAL_SEEDING_TIME);
|
||||
torrentParams.inactiveSeedingTimeLimit = resumeDataRoot.dict_find_int_value("qBt-inactiveSeedingTimeLimit", Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME);
|
||||
torrentParams.shareLimitAction = Utils::String::toEnum(
|
||||
fromLTString(resumeDataRoot.dict_find_string_value("qBt-shareLimitAction")), ShareLimitAction::Default);
|
||||
|
||||
torrentParams.savePath = Profile::instance()->fromPortablePath(
|
||||
Path(fromLTString(resumeDataRoot.dict_find_string_value("qBt-savePath"))));
|
||||
Path(fromLTString(resumeDataRoot.dict_find_string_value("qBt-savePath"))));
|
||||
torrentParams.useAutoTMM = torrentParams.savePath.isEmpty();
|
||||
if (!torrentParams.useAutoTMM)
|
||||
{
|
||||
torrentParams.downloadPath = Profile::instance()->fromPortablePath(
|
||||
Path(fromLTString(resumeDataRoot.dict_find_string_value("qBt-downloadPath"))));
|
||||
Path(fromLTString(resumeDataRoot.dict_find_string_value("qBt-downloadPath"))));
|
||||
}
|
||||
|
||||
// TODO: The following code is deprecated. Replace with the commented one after several releases in 4.4.x.
|
||||
@@ -261,7 +263,7 @@ BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorre
|
||||
// === END REPLACEMENT CODE === //
|
||||
|
||||
torrentParams.stopCondition = Utils::String::toEnum(
|
||||
fromLTString(resumeDataRoot.dict_find_string_value("qBt-stopCondition")), Torrent::StopCondition::None);
|
||||
fromLTString(resumeDataRoot.dict_find_string_value("qBt-stopCondition")), Torrent::StopCondition::None);
|
||||
torrentParams.sslParameters =
|
||||
{
|
||||
.certificate = QSslCertificate(toByteArray(resumeDataRoot.dict_find_string_value(KEY_SSL_CERTIFICATE))),
|
||||
@@ -418,6 +420,8 @@ void BitTorrent::BencodeResumeDataStorage::Worker::store(const TorrentID &id, co
|
||||
data["qBt-ratioLimit"] = static_cast<int>(resumeData.ratioLimit * 1000);
|
||||
data["qBt-seedingTimeLimit"] = resumeData.seedingTimeLimit;
|
||||
data["qBt-inactiveSeedingTimeLimit"] = resumeData.inactiveSeedingTimeLimit;
|
||||
data["qBt-shareLimitAction"] = Utils::String::fromEnum(resumeData.shareLimitAction).toStdString();
|
||||
|
||||
data["qBt-category"] = resumeData.category.toStdString();
|
||||
data["qBt-tags"] = setToEntryList(resumeData.tags);
|
||||
data["qBt-name"] = resumeData.name.toStdString();
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace
|
||||
{
|
||||
const QString DB_CONNECTION_NAME = u"ResumeDataStorage"_s;
|
||||
|
||||
const int DB_VERSION = 6;
|
||||
const int DB_VERSION = 7;
|
||||
|
||||
const QString DB_TABLE_META = u"meta"_s;
|
||||
const QString DB_TABLE_TORRENTS = u"torrents"_s;
|
||||
@@ -138,6 +138,7 @@ namespace
|
||||
const Column DB_COLUMN_RATIO_LIMIT = makeColumn("ratio_limit");
|
||||
const Column DB_COLUMN_SEEDING_TIME_LIMIT = makeColumn("seeding_time_limit");
|
||||
const Column DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT = makeColumn("inactive_seeding_time_limit");
|
||||
const Column DB_COLUMN_SHARE_LIMIT_ACTION = makeColumn("share_limit_action");
|
||||
const Column DB_COLUMN_HAS_OUTER_PIECES_PRIORITY = makeColumn("has_outer_pieces_priority");
|
||||
const Column DB_COLUMN_HAS_SEED_STATUS = makeColumn("has_seed_status");
|
||||
const Column DB_COLUMN_OPERATING_MODE = makeColumn("operating_mode");
|
||||
@@ -234,13 +235,15 @@ namespace
|
||||
resumeData.ratioLimit = query.value(DB_COLUMN_RATIO_LIMIT.name).toInt() / 1000.0;
|
||||
resumeData.seedingTimeLimit = query.value(DB_COLUMN_SEEDING_TIME_LIMIT.name).toInt();
|
||||
resumeData.inactiveSeedingTimeLimit = query.value(DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT.name).toInt();
|
||||
resumeData.shareLimitAction = Utils::String::toEnum<ShareLimitAction>(
|
||||
query.value(DB_COLUMN_SHARE_LIMIT_ACTION.name).toString(), ShareLimitAction::Default);
|
||||
resumeData.contentLayout = Utils::String::toEnum<TorrentContentLayout>(
|
||||
query.value(DB_COLUMN_CONTENT_LAYOUT.name).toString(), TorrentContentLayout::Original);
|
||||
query.value(DB_COLUMN_CONTENT_LAYOUT.name).toString(), TorrentContentLayout::Original);
|
||||
resumeData.operatingMode = Utils::String::toEnum<TorrentOperatingMode>(
|
||||
query.value(DB_COLUMN_OPERATING_MODE.name).toString(), TorrentOperatingMode::AutoManaged);
|
||||
query.value(DB_COLUMN_OPERATING_MODE.name).toString(), TorrentOperatingMode::AutoManaged);
|
||||
resumeData.stopped = query.value(DB_COLUMN_STOPPED.name).toBool();
|
||||
resumeData.stopCondition = Utils::String::toEnum(
|
||||
query.value(DB_COLUMN_STOP_CONDITION.name).toString(), Torrent::StopCondition::None);
|
||||
query.value(DB_COLUMN_STOP_CONDITION.name).toString(), Torrent::StopCondition::None);
|
||||
resumeData.sslParameters =
|
||||
{
|
||||
.certificate = QSslCertificate(query.value(DB_COLUMN_SSL_CERTIFICATE.name).toByteArray()),
|
||||
@@ -540,6 +543,7 @@ void BitTorrent::DBResumeDataStorage::createDB() const
|
||||
makeColumnDefinition(DB_COLUMN_RATIO_LIMIT, "INTEGER NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_SEEDING_TIME_LIMIT, "INTEGER NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT, "INTEGER NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_SHARE_LIMIT_ACTION, "TEXT NOT NULL DEFAULT `Default`"),
|
||||
makeColumnDefinition(DB_COLUMN_HAS_OUTER_PIECES_PRIORITY, "INTEGER NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_HAS_SEED_STATUS, "INTEGER NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_OPERATING_MODE, "TEXT NOT NULL"),
|
||||
@@ -623,6 +627,9 @@ void BitTorrent::DBResumeDataStorage::updateDB(const int fromVersion) const
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_SSL_DH_PARAMS, "TEXT");
|
||||
}
|
||||
|
||||
if (fromVersion <= 6)
|
||||
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_SHARE_LIMIT_ACTION, "TEXTNOT NULL DEFAULT `Default`");
|
||||
|
||||
const QString updateMetaVersionQuery = makeUpdateStatement(DB_TABLE_META, {DB_COLUMN_NAME, DB_COLUMN_VALUE});
|
||||
if (!query.prepare(updateMetaVersionQuery))
|
||||
throw RuntimeError(query.lastError().text());
|
||||
@@ -801,6 +808,7 @@ namespace
|
||||
DB_COLUMN_RATIO_LIMIT,
|
||||
DB_COLUMN_SEEDING_TIME_LIMIT,
|
||||
DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT,
|
||||
DB_COLUMN_SHARE_LIMIT_ACTION,
|
||||
DB_COLUMN_HAS_OUTER_PIECES_PRIORITY,
|
||||
DB_COLUMN_HAS_SEED_STATUS,
|
||||
DB_COLUMN_OPERATING_MODE,
|
||||
@@ -863,6 +871,7 @@ namespace
|
||||
query.bindValue(DB_COLUMN_RATIO_LIMIT.placeholder, static_cast<int>(m_resumeData.ratioLimit * 1000));
|
||||
query.bindValue(DB_COLUMN_SEEDING_TIME_LIMIT.placeholder, m_resumeData.seedingTimeLimit);
|
||||
query.bindValue(DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT.placeholder, m_resumeData.inactiveSeedingTimeLimit);
|
||||
query.bindValue(DB_COLUMN_SHARE_LIMIT_ACTION.placeholder, Utils::String::fromEnum(m_resumeData.shareLimitAction));
|
||||
query.bindValue(DB_COLUMN_HAS_OUTER_PIECES_PRIORITY.placeholder, m_resumeData.firstLastPiecePriority);
|
||||
query.bindValue(DB_COLUMN_HAS_SEED_STATUS.placeholder, m_resumeData.hasFinishedStatus);
|
||||
query.bindValue(DB_COLUMN_OPERATING_MODE.placeholder, Utils::String::fromEnum(m_resumeData.operatingMode));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2021 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2021-2024 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
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include "base/path.h"
|
||||
#include "base/tagset.h"
|
||||
#include "sharelimitaction.h"
|
||||
#include "sslparameters.h"
|
||||
#include "torrent.h"
|
||||
#include "torrentcontentlayout.h"
|
||||
@@ -62,6 +63,8 @@ namespace BitTorrent
|
||||
qreal ratioLimit = Torrent::USE_GLOBAL_RATIO;
|
||||
int seedingTimeLimit = Torrent::USE_GLOBAL_SEEDING_TIME;
|
||||
int inactiveSeedingTimeLimit = Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME;
|
||||
ShareLimitAction shareLimitAction = ShareLimitAction::Default;
|
||||
|
||||
SSLParameters sslParameters;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015-2023 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -36,20 +36,11 @@
|
||||
#include "base/tagset.h"
|
||||
#include "addtorrentparams.h"
|
||||
#include "categoryoptions.h"
|
||||
#include "sharelimitaction.h"
|
||||
#include "trackerentry.h"
|
||||
|
||||
class QString;
|
||||
|
||||
// These values should remain unchanged when adding new items
|
||||
// so as not to break the existing user settings.
|
||||
enum MaxRatioAction
|
||||
{
|
||||
Pause = 0,
|
||||
Remove = 1,
|
||||
DeleteFiles = 3,
|
||||
EnableSuperSeeding = 2
|
||||
};
|
||||
|
||||
enum DeleteOption
|
||||
{
|
||||
DeleteTorrent,
|
||||
@@ -209,6 +200,9 @@ namespace BitTorrent
|
||||
virtual void setGlobalMaxSeedingMinutes(int minutes) = 0;
|
||||
virtual int globalMaxInactiveSeedingMinutes() const = 0;
|
||||
virtual void setGlobalMaxInactiveSeedingMinutes(int minutes) = 0;
|
||||
virtual ShareLimitAction shareLimitAction() const = 0;
|
||||
virtual void setShareLimitAction(ShareLimitAction act) = 0;
|
||||
|
||||
virtual QString getDHTBootstrapNodes() const = 0;
|
||||
virtual void setDHTBootstrapNodes(const QString &nodes) = 0;
|
||||
virtual bool isDHTEnabled() const = 0;
|
||||
@@ -446,9 +440,6 @@ namespace BitTorrent
|
||||
virtual const CacheStatus &cacheStatus() const = 0;
|
||||
virtual bool isListening() const = 0;
|
||||
|
||||
virtual MaxRatioAction maxRatioAction() const = 0;
|
||||
virtual void setMaxRatioAction(MaxRatioAction act) = 0;
|
||||
|
||||
virtual void banIP(const QString &ip) = 0;
|
||||
|
||||
virtual bool isKnownTorrent(const InfoHash &infoHash) const = 0;
|
||||
|
||||
@@ -492,7 +492,8 @@ SessionImpl::SessionImpl(QObject *parent)
|
||||
, m_seedChokingAlgorithm(BITTORRENT_SESSION_KEY(u"SeedChokingAlgorithm"_s), SeedChokingAlgorithm::FastestUpload
|
||||
, clampValue(SeedChokingAlgorithm::RoundRobin, SeedChokingAlgorithm::AntiLeech))
|
||||
, m_storedTags(BITTORRENT_SESSION_KEY(u"Tags"_s))
|
||||
, m_maxRatioAction(BITTORRENT_SESSION_KEY(u"MaxRatioAction"_s), Pause)
|
||||
, m_shareLimitAction(BITTORRENT_SESSION_KEY(u"ShareLimitAction"_s), ShareLimitAction::Stop
|
||||
, [](const ShareLimitAction action) { return (action == ShareLimitAction::Default) ? ShareLimitAction::Stop : action; })
|
||||
, m_savePath(BITTORRENT_SESSION_KEY(u"DefaultSavePath"_s), specialFolderLocation(SpecialFolder::Downloads))
|
||||
, m_downloadPath(BITTORRENT_SESSION_KEY(u"TempPath"_s), (savePath() / Path(u"temp"_s)))
|
||||
, m_isDownloadPathEnabled(BITTORRENT_SESSION_KEY(u"TempPathEnabled"_s), false)
|
||||
@@ -2219,9 +2220,7 @@ void SessionImpl::populateAdditionalTrackers()
|
||||
|
||||
void SessionImpl::processShareLimits()
|
||||
{
|
||||
qDebug("Processing share limits...");
|
||||
|
||||
const auto resolveLimitValue = []<typename T>(const T limit, const T useGlobalLimit, const T globalLimit) -> T
|
||||
const auto effectiveLimit = []<typename T>(const T limit, const T useGlobalLimit, const T globalLimit) -> T
|
||||
{
|
||||
return (limit == useGlobalLimit) ? globalLimit : limit;
|
||||
};
|
||||
@@ -2234,107 +2233,56 @@ void SessionImpl::processShareLimits()
|
||||
if (!torrent->isFinished() || torrent->isForced())
|
||||
continue;
|
||||
|
||||
if (const qreal ratioLimit = resolveLimitValue(torrent->ratioLimit(), Torrent::USE_GLOBAL_RATIO, globalMaxRatio());
|
||||
ratioLimit >= 0)
|
||||
const qreal ratioLimit = effectiveLimit(torrent->ratioLimit(), Torrent::USE_GLOBAL_RATIO, globalMaxRatio());
|
||||
const int seedingTimeLimit = effectiveLimit(torrent->seedingTimeLimit(), Torrent::USE_GLOBAL_SEEDING_TIME, globalMaxSeedingMinutes());
|
||||
const int inactiveSeedingTimeLimit = effectiveLimit(torrent->inactiveSeedingTimeLimit(), Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME, globalMaxInactiveSeedingMinutes());
|
||||
|
||||
bool reached = false;
|
||||
QString description;
|
||||
|
||||
if (const qreal ratio = torrent->realRatio();
|
||||
(ratioLimit >= 0) && (ratio <= Torrent::MAX_RATIO) && (ratio >= ratioLimit))
|
||||
{
|
||||
const qreal ratio = torrent->realRatio();
|
||||
qDebug("Ratio: %f (limit: %f)", ratio, ratioLimit);
|
||||
|
||||
if ((ratio <= Torrent::MAX_RATIO) && (ratio >= ratioLimit))
|
||||
{
|
||||
const QString description = tr("Torrent reached the share ratio limit.");
|
||||
const QString torrentName = tr("Torrent: \"%1\".").arg(torrent->name());
|
||||
|
||||
if (m_maxRatioAction == Remove)
|
||||
{
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Removed torrent."), torrentName));
|
||||
deleteTorrent(torrentID);
|
||||
}
|
||||
else if (m_maxRatioAction == DeleteFiles)
|
||||
{
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Removed torrent and deleted its content."), torrentName));
|
||||
deleteTorrent(torrentID, DeleteTorrentAndFiles);
|
||||
}
|
||||
else if ((m_maxRatioAction == Pause) && !torrent->isPaused())
|
||||
{
|
||||
torrent->pause();
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Torrent paused."), torrentName));
|
||||
}
|
||||
else if ((m_maxRatioAction == EnableSuperSeeding) && !torrent->isPaused() && !torrent->superSeeding())
|
||||
{
|
||||
torrent->setSuperSeeding(true);
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Super seeding enabled."), torrentName));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
reached = true;
|
||||
description = tr("Torrent reached the share ratio limit.");
|
||||
}
|
||||
else if (const qlonglong seedingTimeInMinutes = torrent->finishedTime() / 60;
|
||||
(seedingTimeLimit >= 0) && (seedingTimeInMinutes <= Torrent::MAX_SEEDING_TIME) && (seedingTimeInMinutes >= seedingTimeLimit))
|
||||
{
|
||||
reached = true;
|
||||
description = tr("Torrent reached the seeding time limit.");
|
||||
}
|
||||
else if (const qlonglong inactiveSeedingTimeInMinutes = torrent->timeSinceActivity() / 60;
|
||||
(inactiveSeedingTimeLimit >= 0) && (inactiveSeedingTimeInMinutes <= Torrent::MAX_INACTIVE_SEEDING_TIME) && (inactiveSeedingTimeInMinutes >= inactiveSeedingTimeLimit))
|
||||
{
|
||||
reached = true;
|
||||
description = tr("Torrent reached the inactive seeding time limit.");
|
||||
}
|
||||
|
||||
if (const int seedingTimeLimit = resolveLimitValue(torrent->seedingTimeLimit(), Torrent::USE_GLOBAL_SEEDING_TIME, globalMaxSeedingMinutes());
|
||||
seedingTimeLimit >= 0)
|
||||
if (reached)
|
||||
{
|
||||
const qlonglong seedingTimeInMinutes = torrent->finishedTime() / 60;
|
||||
const QString torrentName = tr("Torrent: \"%1\".").arg(torrent->name());
|
||||
const ShareLimitAction shareLimitAction = (torrent->shareLimitAction() == ShareLimitAction::Default) ? m_shareLimitAction : torrent->shareLimitAction();
|
||||
|
||||
if ((seedingTimeInMinutes <= Torrent::MAX_SEEDING_TIME) && (seedingTimeInMinutes >= seedingTimeLimit))
|
||||
if (shareLimitAction == ShareLimitAction::Remove)
|
||||
{
|
||||
const QString description = tr("Torrent reached the seeding time limit.");
|
||||
const QString torrentName = tr("Torrent: \"%1\".").arg(torrent->name());
|
||||
|
||||
if (m_maxRatioAction == Remove)
|
||||
{
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Removed torrent."), torrentName));
|
||||
deleteTorrent(torrentID);
|
||||
}
|
||||
else if (m_maxRatioAction == DeleteFiles)
|
||||
{
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Removed torrent and deleted its content."), torrentName));
|
||||
deleteTorrent(torrentID, DeleteTorrentAndFiles);
|
||||
}
|
||||
else if ((m_maxRatioAction == Pause) && !torrent->isPaused())
|
||||
{
|
||||
torrent->pause();
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Torrent paused."), torrentName));
|
||||
}
|
||||
else if ((m_maxRatioAction == EnableSuperSeeding) && !torrent->isPaused() && !torrent->superSeeding())
|
||||
{
|
||||
torrent->setSuperSeeding(true);
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Super seeding enabled."), torrentName));
|
||||
}
|
||||
|
||||
continue;
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Removing torrent."), torrentName));
|
||||
deleteTorrent(torrentID);
|
||||
}
|
||||
}
|
||||
|
||||
if (const int inactiveSeedingTimeLimit = resolveLimitValue(torrent->inactiveSeedingTimeLimit(), Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME, globalMaxInactiveSeedingMinutes());
|
||||
inactiveSeedingTimeLimit >= 0)
|
||||
{
|
||||
const qlonglong inactiveSeedingTimeInMinutes = torrent->timeSinceActivity() / 60;
|
||||
|
||||
if ((inactiveSeedingTimeInMinutes <= Torrent::MAX_INACTIVE_SEEDING_TIME) && (inactiveSeedingTimeInMinutes >= inactiveSeedingTimeLimit))
|
||||
else if (shareLimitAction == ShareLimitAction::RemoveWithContent)
|
||||
{
|
||||
const QString description = tr("Torrent reached the inactive seeding time limit.");
|
||||
const QString torrentName = tr("Torrent: \"%1\".").arg(torrent->name());
|
||||
|
||||
if (m_maxRatioAction == Remove)
|
||||
{
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Removed torrent."), torrentName));
|
||||
deleteTorrent(torrentID);
|
||||
}
|
||||
else if (m_maxRatioAction == DeleteFiles)
|
||||
{
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Removed torrent and deleted its content."), torrentName));
|
||||
deleteTorrent(torrentID, DeleteTorrentAndFiles);
|
||||
}
|
||||
else if ((m_maxRatioAction == Pause) && !torrent->isPaused())
|
||||
{
|
||||
torrent->pause();
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Torrent paused."), torrentName));
|
||||
}
|
||||
else if ((m_maxRatioAction == EnableSuperSeeding) && !torrent->isPaused() && !torrent->superSeeding())
|
||||
{
|
||||
torrent->setSuperSeeding(true);
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Super seeding enabled."), torrentName));
|
||||
}
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Removing torrent and deleting its content."), torrentName));
|
||||
deleteTorrent(torrentID, DeleteTorrentAndFiles);
|
||||
}
|
||||
else if ((shareLimitAction == ShareLimitAction::Stop) && !torrent->isPaused())
|
||||
{
|
||||
torrent->pause();
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Torrent paused."), torrentName));
|
||||
}
|
||||
else if ((shareLimitAction == ShareLimitAction::EnableSuperSeeding) && !torrent->isPaused() && !torrent->superSeeding())
|
||||
{
|
||||
torrent->setSuperSeeding(true);
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Super seeding enabled."), torrentName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2654,6 +2602,7 @@ LoadTorrentParams SessionImpl::initLoadTorrentParams(const AddTorrentParams &add
|
||||
loadTorrentParams.ratioLimit = addTorrentParams.ratioLimit;
|
||||
loadTorrentParams.seedingTimeLimit = addTorrentParams.seedingTimeLimit;
|
||||
loadTorrentParams.inactiveSeedingTimeLimit = addTorrentParams.inactiveSeedingTimeLimit;
|
||||
loadTorrentParams.shareLimitAction = addTorrentParams.shareLimitAction;
|
||||
loadTorrentParams.sslParameters = addTorrentParams.sslParameters;
|
||||
|
||||
const QString category = addTorrentParams.category;
|
||||
@@ -4832,14 +4781,16 @@ bool SessionImpl::isListening() const
|
||||
return m_nativeSessionExtension->isSessionListening();
|
||||
}
|
||||
|
||||
MaxRatioAction SessionImpl::maxRatioAction() const
|
||||
ShareLimitAction SessionImpl::shareLimitAction() const
|
||||
{
|
||||
return static_cast<MaxRatioAction>(m_maxRatioAction.get());
|
||||
return m_shareLimitAction;
|
||||
}
|
||||
|
||||
void SessionImpl::setMaxRatioAction(const MaxRatioAction act)
|
||||
void SessionImpl::setShareLimitAction(const ShareLimitAction act)
|
||||
{
|
||||
m_maxRatioAction = static_cast<int>(act);
|
||||
Q_ASSERT(act != ShareLimitAction::Default);
|
||||
|
||||
m_shareLimitAction = act;
|
||||
}
|
||||
|
||||
bool SessionImpl::isKnownTorrent(const InfoHash &infoHash) const
|
||||
|
||||
@@ -176,6 +176,9 @@ namespace BitTorrent
|
||||
void setGlobalMaxSeedingMinutes(int minutes) override;
|
||||
int globalMaxInactiveSeedingMinutes() const override;
|
||||
void setGlobalMaxInactiveSeedingMinutes(int minutes) override;
|
||||
ShareLimitAction shareLimitAction() const override;
|
||||
void setShareLimitAction(ShareLimitAction act) override;
|
||||
|
||||
QString getDHTBootstrapNodes() const override;
|
||||
void setDHTBootstrapNodes(const QString &nodes) override;
|
||||
bool isDHTEnabled() const override;
|
||||
@@ -413,9 +416,6 @@ namespace BitTorrent
|
||||
const CacheStatus &cacheStatus() const override;
|
||||
bool isListening() const override;
|
||||
|
||||
MaxRatioAction maxRatioAction() const override;
|
||||
void setMaxRatioAction(MaxRatioAction act) override;
|
||||
|
||||
void banIP(const QString &ip) override;
|
||||
|
||||
bool isKnownTorrent(const InfoHash &infoHash) const override;
|
||||
@@ -692,7 +692,7 @@ namespace BitTorrent
|
||||
CachedSettingValue<ChokingAlgorithm> m_chokingAlgorithm;
|
||||
CachedSettingValue<SeedChokingAlgorithm> m_seedChokingAlgorithm;
|
||||
CachedSettingValue<QStringList> m_storedTags;
|
||||
CachedSettingValue<int> m_maxRatioAction;
|
||||
CachedSettingValue<ShareLimitAction> m_shareLimitAction;
|
||||
CachedSettingValue<Path> m_savePath;
|
||||
CachedSettingValue<Path> m_downloadPath;
|
||||
CachedSettingValue<bool> m_isDownloadPathEnabled;
|
||||
|
||||
57
src/base/bittorrent/sharelimitaction.h
Normal file
57
src/base/bittorrent/sharelimitaction.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* 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 <QMetaEnum>
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
// Using `Q_ENUM_NS()` without a wrapper namespace in our case is not advised
|
||||
// since `Q_NAMESPACE` cannot be used when the same namespace resides at different files.
|
||||
// https://www.kdab.com/new-qt-5-8-meta-object-support-namespaces/#comment-143779
|
||||
inline namespace ShareLimitActionNS
|
||||
{
|
||||
Q_NAMESPACE
|
||||
|
||||
// These values should remain unchanged when adding new items
|
||||
// so as not to break the existing user settings.
|
||||
enum class ShareLimitAction
|
||||
{
|
||||
Default = -1, // special value
|
||||
|
||||
Stop = 0,
|
||||
Remove = 1,
|
||||
RemoveWithContent = 3,
|
||||
EnableSuperSeeding = 2
|
||||
};
|
||||
|
||||
Q_ENUM_NS(ShareLimitAction)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015-2023 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "base/3rdparty/expected.hpp"
|
||||
#include "base/pathfwd.h"
|
||||
#include "base/tagset.h"
|
||||
#include "sharelimitaction.h"
|
||||
#include "torrentcontenthandler.h"
|
||||
|
||||
class QBitArray;
|
||||
@@ -212,9 +213,16 @@ namespace BitTorrent
|
||||
virtual int piecesHave() const = 0;
|
||||
virtual qreal progress() const = 0;
|
||||
virtual QDateTime addedTime() const = 0;
|
||||
|
||||
// Share limits
|
||||
virtual qreal ratioLimit() const = 0;
|
||||
virtual void setRatioLimit(qreal limit) = 0;
|
||||
virtual int seedingTimeLimit() const = 0;
|
||||
virtual void setSeedingTimeLimit(int limit) = 0;
|
||||
virtual int inactiveSeedingTimeLimit() const = 0;
|
||||
virtual void setInactiveSeedingTimeLimit(int limit) = 0;
|
||||
virtual ShareLimitAction shareLimitAction() const = 0;
|
||||
virtual void setShareLimitAction(ShareLimitAction action) = 0;
|
||||
|
||||
virtual PathList filePaths() const = 0;
|
||||
|
||||
@@ -287,9 +295,6 @@ namespace BitTorrent
|
||||
virtual void forceReannounce(int index = -1) = 0;
|
||||
virtual void forceDHTAnnounce() = 0;
|
||||
virtual void forceRecheck() = 0;
|
||||
virtual void setRatioLimit(qreal limit) = 0;
|
||||
virtual void setSeedingTimeLimit(int limit) = 0;
|
||||
virtual void setInactiveSeedingTimeLimit(int limit) = 0;
|
||||
virtual void setUploadLimit(int limit) = 0;
|
||||
virtual void setDownloadLimit(int limit) = 0;
|
||||
virtual void setSuperSeeding(bool enable) = 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015-2023 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -298,6 +298,7 @@ TorrentImpl::TorrentImpl(SessionImpl *session, lt::session *nativeSession
|
||||
, m_ratioLimit(params.ratioLimit)
|
||||
, m_seedingTimeLimit(params.seedingTimeLimit)
|
||||
, m_inactiveSeedingTimeLimit(params.inactiveSeedingTimeLimit)
|
||||
, m_shareLimitAction(params.shareLimitAction)
|
||||
, m_operatingMode(params.operatingMode)
|
||||
, m_contentLayout(params.contentLayout)
|
||||
, m_hasFinishedStatus(params.hasFinishedStatus)
|
||||
@@ -2143,6 +2144,7 @@ void TorrentImpl::prepareResumeData(const lt::add_torrent_params ¶ms)
|
||||
.ratioLimit = m_ratioLimit,
|
||||
.seedingTimeLimit = m_seedingTimeLimit,
|
||||
.inactiveSeedingTimeLimit = m_inactiveSeedingTimeLimit,
|
||||
.shareLimitAction = m_shareLimitAction,
|
||||
.sslParameters = m_sslParams
|
||||
};
|
||||
|
||||
@@ -2618,6 +2620,21 @@ void TorrentImpl::setInactiveSeedingTimeLimit(int limit)
|
||||
}
|
||||
}
|
||||
|
||||
ShareLimitAction TorrentImpl::shareLimitAction() const
|
||||
{
|
||||
return m_shareLimitAction;
|
||||
}
|
||||
|
||||
void TorrentImpl::setShareLimitAction(const ShareLimitAction action)
|
||||
{
|
||||
if (m_shareLimitAction != action)
|
||||
{
|
||||
m_shareLimitAction = action;
|
||||
deferredRequestResumeData();
|
||||
m_session->handleTorrentShareLimitChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentImpl::setUploadLimit(const int limit)
|
||||
{
|
||||
const int cleanValue = cleanLimitValue(limit);
|
||||
|
||||
@@ -139,9 +139,15 @@ namespace BitTorrent
|
||||
int piecesHave() const override;
|
||||
qreal progress() const override;
|
||||
QDateTime addedTime() const override;
|
||||
|
||||
qreal ratioLimit() const override;
|
||||
void setRatioLimit(qreal limit) override;
|
||||
int seedingTimeLimit() const override;
|
||||
void setSeedingTimeLimit(int limit) override;
|
||||
int inactiveSeedingTimeLimit() const override;
|
||||
void setInactiveSeedingTimeLimit(int limit) override;
|
||||
ShareLimitAction shareLimitAction() const override;
|
||||
void setShareLimitAction(ShareLimitAction action) override;
|
||||
|
||||
Path filePath(int index) const override;
|
||||
Path actualFilePath(int index) const override;
|
||||
@@ -223,9 +229,6 @@ namespace BitTorrent
|
||||
void forceRecheck() override;
|
||||
void renameFile(int index, const Path &path) override;
|
||||
void prioritizeFiles(const QVector<DownloadPriority> &priorities) override;
|
||||
void setRatioLimit(qreal limit) override;
|
||||
void setSeedingTimeLimit(int limit) override;
|
||||
void setInactiveSeedingTimeLimit(int limit) override;
|
||||
void setUploadLimit(int limit) override;
|
||||
void setDownloadLimit(int limit) override;
|
||||
void setSuperSeeding(bool enable) override;
|
||||
@@ -356,16 +359,17 @@ namespace BitTorrent
|
||||
Path m_downloadPath;
|
||||
QString m_category;
|
||||
TagSet m_tags;
|
||||
qreal m_ratioLimit;
|
||||
int m_seedingTimeLimit;
|
||||
int m_inactiveSeedingTimeLimit;
|
||||
TorrentOperatingMode m_operatingMode;
|
||||
TorrentContentLayout m_contentLayout;
|
||||
bool m_hasFinishedStatus;
|
||||
qreal m_ratioLimit = 0;
|
||||
int m_seedingTimeLimit = 0;
|
||||
int m_inactiveSeedingTimeLimit = 0;
|
||||
ShareLimitAction m_shareLimitAction = ShareLimitAction::Default;
|
||||
TorrentOperatingMode m_operatingMode = TorrentOperatingMode::AutoManaged;
|
||||
TorrentContentLayout m_contentLayout = TorrentContentLayout::Original;
|
||||
bool m_hasFinishedStatus = false;
|
||||
bool m_hasMissingFiles = false;
|
||||
bool m_hasFirstLastPiecePriority = false;
|
||||
bool m_useAutoTMM;
|
||||
bool m_isStopped;
|
||||
bool m_useAutoTMM = false;
|
||||
bool m_isStopped = false;
|
||||
StopCondition m_stopCondition = StopCondition::None;
|
||||
SSLParameters m_sslParams;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user