diff --git a/src/app/upgrade.cpp b/src/app/upgrade.cpp index 5a9d9b896..325b07ec6 100644 --- a/src/app/upgrade.cpp +++ b/src/app/upgrade.cpp @@ -32,7 +32,7 @@ #include #include -#include "base/bittorrent/sharelimitaction.h" +#include "base/bittorrent/sharelimits.h" #include "base/bittorrent/torrentcontentlayout.h" #include "base/global.h" #include "base/logger.h" diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index 7527aefdd..704bbcd77 100644 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -34,7 +34,7 @@ add_library(qbt_base STATIC bittorrent/session.h bittorrent/sessionimpl.h bittorrent/sessionstatus.h - bittorrent/sharelimitaction.h + bittorrent/sharelimits.h bittorrent/speedmonitor.h bittorrent/sslparameters.h bittorrent/torrent.h diff --git a/src/base/bittorrent/addtorrentparams.cpp b/src/base/bittorrent/addtorrentparams.cpp index d284b36d3..11d8a3cc9 100644 --- a/src/base/bittorrent/addtorrentparams.cpp +++ b/src/base/bittorrent/addtorrentparams.cpp @@ -125,9 +125,9 @@ BitTorrent::AddTorrentParams BitTorrent::parseAddTorrentParams(const QJsonObject .useAutoTMM = getOptionalBool(jsonObj, PARAM_AUTOTMM), .uploadLimit = jsonObj.value(PARAM_UPLOADLIMIT).toInt(-1), .downloadLimit = jsonObj.value(PARAM_DOWNLOADLIMIT).toInt(-1), - .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), + .seedingTimeLimit = jsonObj.value(PARAM_SEEDINGTIMELIMIT).toInt(DEFAULT_SEEDING_TIME_LIMIT), + .inactiveSeedingTimeLimit = jsonObj.value(PARAM_INACTIVESEEDINGTIMELIMIT).toInt(DEFAULT_SEEDING_TIME_LIMIT), + .ratioLimit = jsonObj.value(PARAM_RATIOLIMIT).toDouble(DEFAULT_RATIO_LIMIT), .shareLimitAction = getEnum(jsonObj, PARAM_SHARELIMITACTION, ShareLimitAction::Default), .sslParameters = { diff --git a/src/base/bittorrent/addtorrentparams.h b/src/base/bittorrent/addtorrentparams.h index a2de0b725..a663bad3c 100644 --- a/src/base/bittorrent/addtorrentparams.h +++ b/src/base/bittorrent/addtorrentparams.h @@ -36,7 +36,7 @@ #include "base/path.h" #include "base/tagset.h" -#include "sharelimitaction.h" +#include "sharelimits.h" #include "sslparameters.h" #include "torrent.h" #include "torrentcontentlayout.h" @@ -68,9 +68,9 @@ namespace BitTorrent std::optional useAutoTMM; int uploadLimit = -1; int downloadLimit = -1; - int seedingTimeLimit = Torrent::USE_GLOBAL_SEEDING_TIME; - int inactiveSeedingTimeLimit = Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME; - qreal ratioLimit = Torrent::USE_GLOBAL_RATIO; + int seedingTimeLimit = DEFAULT_SEEDING_TIME_LIMIT; + int inactiveSeedingTimeLimit = DEFAULT_SEEDING_TIME_LIMIT; + qreal ratioLimit = DEFAULT_RATIO_LIMIT; ShareLimitAction shareLimitAction = ShareLimitAction::Default; SSLParameters sslParameters; diff --git a/src/base/bittorrent/bencoderesumedatastorage.cpp b/src/base/bittorrent/bencoderesumedatastorage.cpp index ee87b5601..336ad7ce8 100644 --- a/src/base/bittorrent/bencoderesumedatastorage.cpp +++ b/src/base/bittorrent/bencoderesumedatastorage.cpp @@ -239,8 +239,8 @@ BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorre torrentParams.comment = fromLTString(resumeDataRoot.dict_find_string_value("qBt-comment")); torrentParams.hasFinishedStatus = resumeDataRoot.dict_find_int_value("qBt-seedStatus"); 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.seedingTimeLimit = resumeDataRoot.dict_find_int_value("qBt-seedingTimeLimit", DEFAULT_SEEDING_TIME_LIMIT); + torrentParams.inactiveSeedingTimeLimit = resumeDataRoot.dict_find_int_value("qBt-inactiveSeedingTimeLimit", DEFAULT_SEEDING_TIME_LIMIT); torrentParams.shareLimitAction = Utils::String::toEnum( fromLTString(resumeDataRoot.dict_find_string_value("qBt-shareLimitAction")), ShareLimitAction::Default); @@ -283,7 +283,7 @@ BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorre const lt::string_view ratioLimitString = resumeDataRoot.dict_find_string_value("qBt-ratioLimit"); if (ratioLimitString.empty()) - torrentParams.ratioLimit = resumeDataRoot.dict_find_int_value("qBt-ratioLimit", Torrent::USE_GLOBAL_RATIO * 1000) / 1000.0; + torrentParams.ratioLimit = resumeDataRoot.dict_find_int_value("qBt-ratioLimit", DEFAULT_RATIO_LIMIT * 1000) / 1000.0; else torrentParams.ratioLimit = fromLTString(ratioLimitString).toDouble(); diff --git a/src/base/bittorrent/categoryoptions.cpp b/src/base/bittorrent/categoryoptions.cpp index c839670c6..b7b39102a 100644 --- a/src/base/bittorrent/categoryoptions.cpp +++ b/src/base/bittorrent/categoryoptions.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2021-2023 Vladimir Golovnev + * Copyright (C) 2021-2025 Vladimir Golovnev * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -32,10 +32,16 @@ #include #include "base/global.h" +#include "base/utils/string.h" const QString OPTION_SAVEPATH = u"save_path"_s; const QString OPTION_DOWNLOADPATH = u"download_path"_s; +const QString OPTION_RATIOLIMIT = u"ratio_limit"_s; +const QString OPTION_SEEDINGTIMELIMIT = u"seeding_time_limit"_s; +const QString OPTION_INACTIVESEEDINGTIMELIMIT = u"inactive_seeding_time_limit"_s; +const QString OPTION_SHARELIMITACTION = u"share_limit_action"_s; + BitTorrent::CategoryOptions BitTorrent::CategoryOptions::fromJSON(const QJsonObject &jsonObj) { CategoryOptions options; @@ -47,6 +53,11 @@ BitTorrent::CategoryOptions BitTorrent::CategoryOptions::fromJSON(const QJsonObj else if (downloadPathValue.isString()) options.downloadPath = {true, Path(downloadPathValue.toString())}; + options.ratioLimit = jsonObj.value(OPTION_RATIOLIMIT).toDouble(DEFAULT_RATIO_LIMIT); + options.seedingTimeLimit = jsonObj.value(OPTION_SEEDINGTIMELIMIT).toInt(DEFAULT_SEEDING_TIME_LIMIT); + options.inactiveSeedingTimeLimit = jsonObj.value(OPTION_INACTIVESEEDINGTIMELIMIT).toInt(DEFAULT_SEEDING_TIME_LIMIT); + options.shareLimitAction = Utils::String::toEnum(jsonObj.value(OPTION_SHARELIMITACTION).toString(), ShareLimitAction::Default); + return options; } @@ -63,12 +74,10 @@ QJsonObject BitTorrent::CategoryOptions::toJSON() const return { {OPTION_SAVEPATH, savePath.data()}, - {OPTION_DOWNLOADPATH, downloadPathValue} + {OPTION_DOWNLOADPATH, downloadPathValue}, + {OPTION_RATIOLIMIT, ratioLimit}, + {OPTION_SEEDINGTIMELIMIT, seedingTimeLimit}, + {OPTION_INACTIVESEEDINGTIMELIMIT, inactiveSeedingTimeLimit}, + {OPTION_SHARELIMITACTION, Utils::String::fromEnum(shareLimitAction)} }; } - -bool BitTorrent::operator==(const BitTorrent::CategoryOptions &left, const BitTorrent::CategoryOptions &right) -{ - return ((left.savePath == right.savePath) - && (left.downloadPath == right.downloadPath)); -} diff --git a/src/base/bittorrent/categoryoptions.h b/src/base/bittorrent/categoryoptions.h index cbf8fedce..04e96a244 100644 --- a/src/base/bittorrent/categoryoptions.h +++ b/src/base/bittorrent/categoryoptions.h @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2021-2023 Vladimir Golovnev + * Copyright (C) 2021-2025 Vladimir Golovnev * * 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 "downloadpathoption.h" +#include "sharelimits.h" class QJsonObject; @@ -44,9 +45,14 @@ namespace BitTorrent Path savePath; std::optional downloadPath; + qreal ratioLimit = DEFAULT_RATIO_LIMIT; + int seedingTimeLimit = DEFAULT_SEEDING_TIME_LIMIT; + int inactiveSeedingTimeLimit = DEFAULT_SEEDING_TIME_LIMIT; + ShareLimitAction shareLimitAction = ShareLimitAction::Default; + static CategoryOptions fromJSON(const QJsonObject &jsonObj); QJsonObject toJSON() const; - }; - bool operator==(const CategoryOptions &left, const CategoryOptions &right); + friend bool operator==(const CategoryOptions &, const CategoryOptions &) = default; + }; } diff --git a/src/base/bittorrent/loadtorrentparams.h b/src/base/bittorrent/loadtorrentparams.h index 24ebc10d1..11e709cf3 100644 --- a/src/base/bittorrent/loadtorrentparams.h +++ b/src/base/bittorrent/loadtorrentparams.h @@ -34,7 +34,7 @@ #include "base/path.h" #include "base/tagset.h" -#include "sharelimitaction.h" +#include "sharelimits.h" #include "sslparameters.h" #include "torrent.h" #include "torrentcontentlayout.h" @@ -61,9 +61,9 @@ namespace BitTorrent bool addToQueueTop = false; // only for new torrents - qreal ratioLimit = Torrent::USE_GLOBAL_RATIO; - int seedingTimeLimit = Torrent::USE_GLOBAL_SEEDING_TIME; - int inactiveSeedingTimeLimit = Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME; + qreal ratioLimit = DEFAULT_RATIO_LIMIT; + int seedingTimeLimit = DEFAULT_SEEDING_TIME_LIMIT; + int inactiveSeedingTimeLimit = DEFAULT_SEEDING_TIME_LIMIT; ShareLimitAction shareLimitAction = ShareLimitAction::Default; SSLParameters sslParameters; diff --git a/src/base/bittorrent/session.h b/src/base/bittorrent/session.h index 5400f3843..a9e9d6e86 100644 --- a/src/base/bittorrent/session.h +++ b/src/base/bittorrent/session.h @@ -37,7 +37,7 @@ #include "addtorrenterror.h" #include "addtorrentparams.h" #include "categoryoptions.h" -#include "sharelimitaction.h" +#include "sharelimits.h" #include "torrentcontentremoveoption.h" #include "trackerentry.h" #include "trackerentrystatus.h" @@ -158,12 +158,16 @@ namespace BitTorrent virtual QStringList categories() const = 0; virtual CategoryOptions categoryOptions(const QString &categoryName) const = 0; + virtual bool setCategoryOptions(const QString &categoryName, const CategoryOptions &options) = 0; virtual Path categorySavePath(const QString &categoryName) const = 0; virtual Path categorySavePath(const QString &categoryName, const CategoryOptions &options) const = 0; virtual Path categoryDownloadPath(const QString &categoryName) const = 0; virtual Path categoryDownloadPath(const QString &categoryName, const CategoryOptions &options) const = 0; + virtual qreal categoryRatioLimit(const QString &categoryName) const = 0; + virtual int categorySeedingTimeLimit(const QString &categoryName) const = 0; + virtual int categoryInactiveSeedingTimeLimit(const QString &categoryName) const = 0; + virtual ShareLimitAction categoryShareLimitAction(const QString &categoryName) const = 0; virtual bool addCategory(const QString &name, const CategoryOptions &options = {}) = 0; - virtual bool editCategory(const QString &name, const CategoryOptions &options) = 0; virtual bool removeCategory(const QString &name) = 0; virtual bool useCategoryPathsInManualMode() const = 0; virtual void setUseCategoryPathsInManualMode(bool value) = 0; diff --git a/src/base/bittorrent/sessionimpl.cpp b/src/base/bittorrent/sessionimpl.cpp index 7827b50e1..e8e94d591 100644 --- a/src/base/bittorrent/sessionimpl.cpp +++ b/src/base/bittorrent/sessionimpl.cpp @@ -513,9 +513,9 @@ SessionImpl::SessionImpl(QObject *parent) , m_additionalTrackersURL(BITTORRENT_SESSION_KEY(u"AdditionalTrackersURL"_s)) , m_globalMaxRatio(BITTORRENT_SESSION_KEY(u"GlobalMaxRatio"_s), -1, [](qreal r) { return r < 0 ? -1. : r; }) , m_globalMaxSeedingMinutes(BITTORRENT_SESSION_KEY(u"GlobalMaxSeedingMinutes"_s) - , Torrent::NO_SEEDING_TIME_LIMIT, lowerLimited(Torrent::NO_SEEDING_TIME_LIMIT)) + , NO_SEEDING_TIME_LIMIT, lowerLimited(NO_SEEDING_TIME_LIMIT)) , m_globalMaxInactiveSeedingMinutes(BITTORRENT_SESSION_KEY(u"GlobalMaxInactiveSeedingMinutes"_s) - , Torrent::NO_INACTIVE_SEEDING_TIME_LIMIT, lowerLimited(Torrent::NO_INACTIVE_SEEDING_TIME_LIMIT)) + , NO_SEEDING_TIME_LIMIT, lowerLimited(NO_SEEDING_TIME_LIMIT)) , m_isAddTorrentToQueueTop(BITTORRENT_SESSION_KEY(u"AddTorrentToTopOfQueue"_s), false) , m_isAddTorrentStopped(BITTORRENT_SESSION_KEY(u"AddTorrentStopped"_s), false) , m_torrentStopCondition(BITTORRENT_SESSION_KEY(u"TorrentStopCondition"_s), Torrent::StopCondition::None) @@ -972,6 +972,62 @@ Path SessionImpl::categoryDownloadPath(const QString &categoryName, const Catego return (basePath / path); } +qreal SessionImpl::categoryRatioLimit(const QString &categoryName) const +{ + if (categoryName.isEmpty()) + return globalMaxRatio(); + + if (const auto ratioLimit = categoryOptions(categoryName).ratioLimit; + ratioLimit != DEFAULT_RATIO_LIMIT) + { + return ratioLimit; + } + + return categoryRatioLimit(parentCategoryName(categoryName)); +} + +int SessionImpl::categorySeedingTimeLimit(const QString &categoryName) const +{ + if (categoryName.isEmpty()) + return globalMaxSeedingMinutes(); + + if (const auto seedingTimeLimit = categoryOptions(categoryName).seedingTimeLimit; + seedingTimeLimit != DEFAULT_SEEDING_TIME_LIMIT) + { + return seedingTimeLimit; + } + + return categorySeedingTimeLimit(parentCategoryName(categoryName)); +} + +int SessionImpl::categoryInactiveSeedingTimeLimit(const QString &categoryName) const +{ + if (categoryName.isEmpty()) + return globalMaxInactiveSeedingMinutes(); + + if (const auto inactiveSeedingTimeLimit = categoryOptions(categoryName).inactiveSeedingTimeLimit; + inactiveSeedingTimeLimit != DEFAULT_SEEDING_TIME_LIMIT) + { + return inactiveSeedingTimeLimit; + } + + return categoryInactiveSeedingTimeLimit(parentCategoryName(categoryName)); +} + +ShareLimitAction SessionImpl::categoryShareLimitAction(const QString &categoryName) const +{ + if (categoryName.isEmpty()) + return shareLimitAction(); + + if (const auto shareLimitAction = categoryOptions(categoryName).shareLimitAction; + shareLimitAction != ShareLimitAction::Default) + { + return shareLimitAction; + } + + return categoryShareLimitAction(parentCategoryName(categoryName)); +} + DownloadPathOption SessionImpl::resolveCategoryDownloadPathOption(const QString &categoryName, const std::optional &option) const { if (categoryName.isEmpty()) @@ -1008,9 +1064,9 @@ bool SessionImpl::addCategory(const QString &name, const CategoryOptions &option return true; } -bool SessionImpl::editCategory(const QString &name, const CategoryOptions &options) +bool SessionImpl::setCategoryOptions(const QString &categoryName, const CategoryOptions &options) { - const auto it = m_categories.find(name); + const auto it = m_categories.find(categoryName); if (it == m_categories.end()) return false; @@ -1018,14 +1074,15 @@ bool SessionImpl::editCategory(const QString &name, const CategoryOptions &optio if (options == currentOptions) return false; - if (isDisableAutoTMMWhenCategorySavePathChanged()) + if (isDisableAutoTMMWhenCategorySavePathChanged() + && ((options.savePath != currentOptions.savePath) || (options.downloadPath != currentOptions.downloadPath))) { // This should be done before changing the category options // to prevent the torrent from being moved at the new save path. for (TorrentImpl *const torrent : asConst(m_torrents)) { - if (torrent->category() == name) + if (torrent->category() == categoryName) torrent->setAutoTMMEnabled(false); } } @@ -1035,11 +1092,11 @@ bool SessionImpl::editCategory(const QString &name, const CategoryOptions &optio for (TorrentImpl *const torrent : asConst(m_torrents)) { - if (torrent->category() == name) + if (torrent->category() == categoryName) torrent->handleCategoryOptionsChanged(); } - emit categoryOptionsChanged(name); + emit categoryOptionsChanged(categoryName); return true; } @@ -1235,7 +1292,7 @@ qreal SessionImpl::globalMaxRatio() const void SessionImpl::setGlobalMaxRatio(qreal ratio) { if (ratio < 0) - ratio = Torrent::NO_RATIO_LIMIT; + ratio = NO_RATIO_LIMIT; if (ratio != globalMaxRatio()) { @@ -1251,7 +1308,7 @@ int SessionImpl::globalMaxSeedingMinutes() const void SessionImpl::setGlobalMaxSeedingMinutes(int minutes) { - minutes = std::max(minutes, Torrent::NO_SEEDING_TIME_LIMIT); + minutes = std::max(minutes, NO_SEEDING_TIME_LIMIT); if (minutes != globalMaxSeedingMinutes()) { @@ -1267,7 +1324,7 @@ int SessionImpl::globalMaxInactiveSeedingMinutes() const void SessionImpl::setGlobalMaxInactiveSeedingMinutes(int minutes) { - minutes = std::max(minutes, Torrent::NO_INACTIVE_SEEDING_TIME_LIMIT); + minutes = std::max(minutes, NO_SEEDING_TIME_LIMIT); if (minutes != globalMaxInactiveSeedingMinutes()) { @@ -2310,14 +2367,9 @@ void SessionImpl::processTorrentShareLimits(TorrentImpl *torrent) if (!torrent->isFinished() || torrent->isForced()) return; - const auto effectiveLimit = [](const T limit, const T useGlobalLimit, const T globalLimit) -> T - { - return (limit == useGlobalLimit) ? globalLimit : limit; - }; - - 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()); + const qreal ratioLimit = torrent->effectiveRatioLimit(); + const int seedingTimeLimit = torrent->effectiveSeedingTimeLimit(); + const int inactiveSeedingTimeLimit = torrent->effectiveInactiveSeedingTimeLimit(); bool reached = false; QString description; @@ -2344,7 +2396,7 @@ void SessionImpl::processTorrentShareLimits(TorrentImpl *torrent) if (reached) { const QString torrentName = tr("Torrent: \"%1\".").arg(torrent->name()); - const ShareLimitAction shareLimitAction = (torrent->shareLimitAction() == ShareLimitAction::Default) ? m_shareLimitAction : torrent->shareLimitAction(); + const ShareLimitAction shareLimitAction = torrent->effectiveShareLimitAction(); if (shareLimitAction == ShareLimitAction::Remove) { @@ -5172,9 +5224,9 @@ bool SessionImpl::isKnownTorrent(const InfoHash &infoHash) const void SessionImpl::updateSeedingLimitTimer() { - if ((globalMaxRatio() == Torrent::NO_RATIO_LIMIT) && !hasPerTorrentRatioLimit() - && (globalMaxSeedingMinutes() == Torrent::NO_SEEDING_TIME_LIMIT) && !hasPerTorrentSeedingTimeLimit() - && (globalMaxInactiveSeedingMinutes() == Torrent::NO_INACTIVE_SEEDING_TIME_LIMIT) && !hasPerTorrentInactiveSeedingTimeLimit()) + if ((globalMaxRatio() == NO_RATIO_LIMIT) && !hasPerTorrentRatioLimit() + && (globalMaxSeedingMinutes() == NO_SEEDING_TIME_LIMIT) && !hasPerTorrentSeedingTimeLimit() + && (globalMaxInactiveSeedingMinutes() == NO_SEEDING_TIME_LIMIT) && !hasPerTorrentInactiveSeedingTimeLimit()) { if (m_seedingLimitTimer->isActive()) m_seedingLimitTimer->stop(); diff --git a/src/base/bittorrent/sessionimpl.h b/src/base/bittorrent/sessionimpl.h index a0daae281..a6d337dfe 100644 --- a/src/base/bittorrent/sessionimpl.h +++ b/src/base/bittorrent/sessionimpl.h @@ -149,12 +149,16 @@ namespace BitTorrent QStringList categories() const override; CategoryOptions categoryOptions(const QString &categoryName) const override; + bool setCategoryOptions(const QString &categoryName, const CategoryOptions &options) override; Path categorySavePath(const QString &categoryName) const override; Path categorySavePath(const QString &categoryName, const CategoryOptions &options) const override; Path categoryDownloadPath(const QString &categoryName) const override; Path categoryDownloadPath(const QString &categoryName, const CategoryOptions &options) const override; + qreal categoryRatioLimit(const QString &categoryName) const override; + int categorySeedingTimeLimit(const QString &categoryName) const override; + int categoryInactiveSeedingTimeLimit(const QString &categoryName) const override; + ShareLimitAction categoryShareLimitAction(const QString &categoryName) const override; bool addCategory(const QString &name, const CategoryOptions &options = {}) override; - bool editCategory(const QString &name, const CategoryOptions &options) override; bool removeCategory(const QString &name) override; bool useCategoryPathsInManualMode() const override; void setUseCategoryPathsInManualMode(bool value) override; diff --git a/src/base/bittorrent/sharelimitaction.h b/src/base/bittorrent/sharelimits.h similarity index 89% rename from src/base/bittorrent/sharelimitaction.h rename to src/base/bittorrent/sharelimits.h index c12b8ac34..3a24fa1cb 100644 --- a/src/base/bittorrent/sharelimitaction.h +++ b/src/base/bittorrent/sharelimits.h @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015-2024 Vladimir Golovnev + * Copyright (C) 2015-2025 Vladimir Golovnev * Copyright (C) 2006 Christophe Dumez * * This program is free software; you can redistribute it and/or @@ -33,6 +33,12 @@ namespace BitTorrent { + inline const qreal DEFAULT_RATIO_LIMIT = -2; + inline const qreal NO_RATIO_LIMIT = -1; + + inline const int DEFAULT_SEEDING_TIME_LIMIT = -2; + inline const int NO_SEEDING_TIME_LIMIT = -1; + // 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 diff --git a/src/base/bittorrent/torrent.cpp b/src/base/bittorrent/torrent.cpp index b8098d77f..82398a1c9 100644 --- a/src/base/bittorrent/torrent.cpp +++ b/src/base/bittorrent/torrent.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev + * Copyright (C) 2015-2025 Vladimir Golovnev * Copyright (C) 2006 Christophe Dumez * * This program is free software; you can redistribute it and/or @@ -44,15 +44,6 @@ namespace BitTorrent // Torrent - const qreal Torrent::USE_GLOBAL_RATIO = -2; - const qreal Torrent::NO_RATIO_LIMIT = -1; - - const int Torrent::USE_GLOBAL_SEEDING_TIME = -2; - const int Torrent::NO_SEEDING_TIME_LIMIT = -1; - - const int Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME = -2; - const int Torrent::NO_INACTIVE_SEEDING_TIME_LIMIT = -1; - const qreal Torrent::MAX_RATIO = std::numeric_limits::infinity(); TorrentID Torrent::id() const diff --git a/src/base/bittorrent/torrent.h b/src/base/bittorrent/torrent.h index 8a2d0bc76..fae478256 100644 --- a/src/base/bittorrent/torrent.h +++ b/src/base/bittorrent/torrent.h @@ -37,7 +37,7 @@ #include "base/3rdparty/expected.hpp" #include "base/pathfwd.h" #include "base/tagset.h" -#include "sharelimitaction.h" +#include "sharelimits.h" #include "torrentannouncestatus.h" #include "torrentcontenthandler.h" @@ -125,15 +125,6 @@ namespace BitTorrent }; Q_ENUM(StopCondition) - static const qreal USE_GLOBAL_RATIO; - static const qreal NO_RATIO_LIMIT; - - static const int USE_GLOBAL_SEEDING_TIME; - static const int NO_SEEDING_TIME_LIMIT; - - static const int USE_GLOBAL_INACTIVE_SEEDING_TIME; - static const int NO_INACTIVE_SEEDING_TIME_LIMIT; - static const qreal MAX_RATIO; using TorrentContentHandler::TorrentContentHandler; @@ -236,6 +227,10 @@ namespace BitTorrent virtual void setInactiveSeedingTimeLimit(int limit) = 0; virtual ShareLimitAction shareLimitAction() const = 0; virtual void setShareLimitAction(ShareLimitAction action) = 0; + virtual qreal effectiveRatioLimit() const = 0; + virtual int effectiveSeedingTimeLimit() const = 0; + virtual int effectiveInactiveSeedingTimeLimit() const = 0; + virtual ShareLimitAction effectiveShareLimitAction() const = 0; virtual PathList filePaths() const = 0; virtual PathList actualFilePaths() const = 0; @@ -279,9 +274,6 @@ namespace BitTorrent virtual bool isLSDDisabled() const = 0; virtual QBitArray pieces() const = 0; virtual qreal distributedCopies() const = 0; - virtual qreal maxRatio() const = 0; - virtual int maxSeedingTime() const = 0; - virtual int maxInactiveSeedingTime() const = 0; virtual qreal realRatio() const = 0; virtual qreal popularity() const = 0; virtual int uploadPayloadRate() const = 0; diff --git a/src/base/bittorrent/torrentimpl.cpp b/src/base/bittorrent/torrentimpl.cpp index b46107325..b20c839f6 100644 --- a/src/base/bittorrent/torrentimpl.cpp +++ b/src/base/bittorrent/torrentimpl.cpp @@ -1338,16 +1338,16 @@ qlonglong TorrentImpl::eta() const if (isFinished()) { - const qreal maxRatioValue = maxRatio(); - const int maxSeedingTimeValue = maxSeedingTime(); - const int maxInactiveSeedingTimeValue = maxInactiveSeedingTime(); - if ((maxRatioValue < 0) && (maxSeedingTimeValue < 0) && (maxInactiveSeedingTimeValue < 0)) return MAX_ETA; + const qreal maxRatioValue = effectiveRatioLimit(); + const int maxSeedingTimeValue = effectiveSeedingTimeLimit(); + const int maxInactiveSeedingTimeValue = effectiveInactiveSeedingTimeLimit(); + if ((maxRatioValue < 0) && (maxSeedingTimeValue < 0) && (maxInactiveSeedingTimeValue < 0)) + return MAX_ETA; qlonglong ratioEta = MAX_ETA; if ((speedAverage.upload > 0) && (maxRatioValue >= 0)) { - qlonglong realDL = totalDownload(); if (realDL <= 0) realDL = wantedSize(); @@ -1479,30 +1479,38 @@ qreal TorrentImpl::distributedCopies() const return m_nativeStatus.distributed_copies; } -qreal TorrentImpl::maxRatio() const +qreal TorrentImpl::effectiveRatioLimit() const { - if (m_ratioLimit == USE_GLOBAL_RATIO) - return m_session->globalMaxRatio(); + if (m_ratioLimit == DEFAULT_RATIO_LIMIT) + return m_session->categoryRatioLimit(category()); return m_ratioLimit; } -int TorrentImpl::maxSeedingTime() const +int TorrentImpl::effectiveSeedingTimeLimit() const { - if (m_seedingTimeLimit == USE_GLOBAL_SEEDING_TIME) - return m_session->globalMaxSeedingMinutes(); + if (m_seedingTimeLimit == DEFAULT_SEEDING_TIME_LIMIT) + return m_session->categorySeedingTimeLimit(category()); return m_seedingTimeLimit; } -int TorrentImpl::maxInactiveSeedingTime() const +int TorrentImpl::effectiveInactiveSeedingTimeLimit() const { - if (m_inactiveSeedingTimeLimit == USE_GLOBAL_INACTIVE_SEEDING_TIME) - return m_session->globalMaxInactiveSeedingMinutes(); + if (m_inactiveSeedingTimeLimit == DEFAULT_SEEDING_TIME_LIMIT) + return m_session->categoryInactiveSeedingTimeLimit(category()); return m_inactiveSeedingTimeLimit; } +ShareLimitAction TorrentImpl::effectiveShareLimitAction() const +{ + if (m_shareLimitAction == ShareLimitAction::Default) + return m_session->categoryShareLimitAction(category()); + + return m_shareLimitAction; +} + qreal TorrentImpl::realRatio() const { const int64_t upload = m_nativeStatus.all_time_upload; @@ -2623,7 +2631,7 @@ void TorrentImpl::updateProgress() void TorrentImpl::setRatioLimit(qreal limit) { - if (limit < USE_GLOBAL_RATIO) + if (limit < DEFAULT_RATIO_LIMIT) limit = NO_RATIO_LIMIT; if (m_ratioLimit != limit) @@ -2636,7 +2644,7 @@ void TorrentImpl::setRatioLimit(qreal limit) void TorrentImpl::setSeedingTimeLimit(int limit) { - if (limit < USE_GLOBAL_SEEDING_TIME) + if (limit < DEFAULT_SEEDING_TIME_LIMIT) limit = NO_SEEDING_TIME_LIMIT; if (m_seedingTimeLimit != limit) @@ -2649,8 +2657,8 @@ void TorrentImpl::setSeedingTimeLimit(int limit) void TorrentImpl::setInactiveSeedingTimeLimit(int limit) { - if (limit < USE_GLOBAL_INACTIVE_SEEDING_TIME) - limit = NO_INACTIVE_SEEDING_TIME_LIMIT; + if (limit < DEFAULT_SEEDING_TIME_LIMIT) + limit = NO_SEEDING_TIME_LIMIT; if (m_inactiveSeedingTimeLimit != limit) { diff --git a/src/base/bittorrent/torrentimpl.h b/src/base/bittorrent/torrentimpl.h index f10c53177..2ed1ee49b 100644 --- a/src/base/bittorrent/torrentimpl.h +++ b/src/base/bittorrent/torrentimpl.h @@ -156,6 +156,10 @@ namespace BitTorrent void setInactiveSeedingTimeLimit(int limit) override; ShareLimitAction shareLimitAction() const override; void setShareLimitAction(ShareLimitAction action) override; + qreal effectiveRatioLimit() const override; + int effectiveSeedingTimeLimit() const override; + int effectiveInactiveSeedingTimeLimit() const override; + ShareLimitAction effectiveShareLimitAction() const override; Path filePath(int index) const override; Path actualFilePath(int index) const override; @@ -205,9 +209,6 @@ namespace BitTorrent bool isLSDDisabled() const override; QBitArray pieces() const override; qreal distributedCopies() const override; - qreal maxRatio() const override; - int maxSeedingTime() const override; - int maxInactiveSeedingTime() const override; qreal realRatio() const override; qreal popularity() const override; int uploadPayloadRate() const override; diff --git a/src/gui/addtorrentparamswidget.cpp b/src/gui/addtorrentparamswidget.cpp index bedf88ffd..bd57a6356 100644 --- a/src/gui/addtorrentparamswidget.cpp +++ b/src/gui/addtorrentparamswidget.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2023 Vladimir Golovnev + * Copyright (C) 2023-2025 Vladimir Golovnev * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -190,6 +190,7 @@ void AddTorrentParamsWidget::populate() } populateDefaultPaths(); + resetShareLimitsWidgetDefaults(); }); m_ui->savePathEdit->disconnect(this); @@ -241,7 +242,7 @@ void AddTorrentParamsWidget::populate() m_ui->startTorrentComboBox->disconnect(this); m_ui->startTorrentComboBox->setCurrentIndex(m_addTorrentParams.addStopped - ? m_ui->startTorrentComboBox->findData(!*m_addTorrentParams.addStopped) : 0); + ? m_ui->startTorrentComboBox->findData(!*m_addTorrentParams.addStopped) : 0); connect(m_ui->startTorrentComboBox, &QComboBox::currentIndexChanged, this, [this] { const QVariant data = m_ui->startTorrentComboBox->currentData(); @@ -270,6 +271,7 @@ void AddTorrentParamsWidget::populate() m_addTorrentParams.addToQueueTop = data.toBool(); }); + resetShareLimitsWidgetDefaults(); m_ui->torrentShareLimitsWidget->setRatioLimit(m_addTorrentParams.ratioLimit); m_ui->torrentShareLimitsWidget->setSeedingTimeLimit(m_addTorrentParams.seedingTimeLimit); m_ui->torrentShareLimitsWidget->setInactiveSeedingTimeLimit(m_addTorrentParams.inactiveSeedingTimeLimit); @@ -418,3 +420,11 @@ void AddTorrentParamsWidget::populateSavePathOptions() populateDefaultPaths(); } + +void AddTorrentParamsWidget::resetShareLimitsWidgetDefaults() +{ + const auto *btSession = BitTorrent::Session::instance(); + m_ui->torrentShareLimitsWidget->setDefaults((m_addTorrentParams.category.isEmpty() ? TorrentShareLimitsWidget::UsedDefaults::Global : TorrentShareLimitsWidget::UsedDefaults::Category) + , btSession->categoryRatioLimit(m_addTorrentParams.category), btSession->categorySeedingTimeLimit(m_addTorrentParams.category) + , btSession->categoryInactiveSeedingTimeLimit(m_addTorrentParams.category), btSession->categoryShareLimitAction(m_addTorrentParams.category)); +} diff --git a/src/gui/addtorrentparamswidget.h b/src/gui/addtorrentparamswidget.h index 3f61e55ae..f804fd2aa 100644 --- a/src/gui/addtorrentparamswidget.h +++ b/src/gui/addtorrentparamswidget.h @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2023 Vladimir Golovnev + * Copyright (C) 2023-2025 Vladimir Golovnev * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -57,7 +57,7 @@ private: void populateDefaultPaths(); void populateDefaultDownloadPath(); void populateSavePathOptions(); - + void resetShareLimitsWidgetDefaults(); Ui::AddTorrentParamsWidget *m_ui; BitTorrent::AddTorrentParams m_addTorrentParams; diff --git a/src/gui/optionsdialog.cpp b/src/gui/optionsdialog.cpp index 4f9d437bf..6dafbbe8b 100644 --- a/src/gui/optionsdialog.cpp +++ b/src/gui/optionsdialog.cpp @@ -48,7 +48,7 @@ #include #include "base/bittorrent/session.h" -#include "base/bittorrent/sharelimitaction.h" +#include "base/bittorrent/sharelimits.h" #include "base/exceptions.h" #include "base/global.h" #include "base/net/downloadmanager.h" diff --git a/src/gui/torrentcategorydialog.cpp b/src/gui/torrentcategorydialog.cpp index ce02d6667..ab5268fd6 100644 --- a/src/gui/torrentcategorydialog.cpp +++ b/src/gui/torrentcategorydialog.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017, 2021 Vladimir Golovnev + * Copyright (C) 2017-2025 Vladimir Golovnev * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -32,11 +32,12 @@ #include #include "base/bittorrent/session.h" -#include "base/utils/fs.h" +#include "base/bittorrent/torrent.h" +#include "torrentsharelimitswidget.h" #include "ui_torrentcategorydialog.h" TorrentCategoryDialog::TorrentCategoryDialog(QWidget *parent) - : QDialog {parent} + : QDialog(parent) , m_ui {new Ui::TorrentCategoryDialog} { m_ui->setupUi(this); @@ -56,6 +57,15 @@ TorrentCategoryDialog::TorrentCategoryDialog(QWidget *parent) connect(m_ui->textCategoryName, &QLineEdit::textChanged, this, &TorrentCategoryDialog::categoryNameChanged); connect(m_ui->comboUseDownloadPath, &QComboBox::currentIndexChanged, this, &TorrentCategoryDialog::useDownloadPathChanged); + + resetShareLimitsWidgetDefaults(); +} + +TorrentCategoryDialog::TorrentCategoryDialog(QWidget *parent, const QString &categoryName, const BitTorrent::CategoryOptions &categoryOptions) + : TorrentCategoryDialog(parent) +{ + setCategoryName(categoryName); + setCategoryOptions(categoryOptions); } TorrentCategoryDialog::~TorrentCategoryDialog() @@ -73,8 +83,7 @@ QString TorrentCategoryDialog::createCategory(QWidget *parent, const QString &pa newCategoryName += u'/'; newCategoryName += tr("New Category"); - TorrentCategoryDialog dialog {parent}; - dialog.setCategoryName(newCategoryName); + TorrentCategoryDialog dialog {parent, newCategoryName, {}}; while (dialog.exec() == TorrentCategoryDialog::Accepted) { newCategoryName = dialog.categoryName(); @@ -110,14 +119,12 @@ void TorrentCategoryDialog::editCategory(QWidget *parent, const QString &categor Q_ASSERT(Session::instance()->categories().contains(categoryName)); - auto *dialog = new TorrentCategoryDialog(parent); + auto *dialog = new TorrentCategoryDialog(parent, categoryName, Session::instance()->categoryOptions(categoryName)); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setCategoryNameEditable(false); - dialog->setCategoryName(categoryName); - dialog->setCategoryOptions(Session::instance()->categoryOptions(categoryName)); connect(dialog, &TorrentCategoryDialog::accepted, parent, [dialog, categoryName]() { - Session::instance()->editCategory(categoryName, dialog->categoryOptions()); + Session::instance()->setCategoryOptions(categoryName, dialog->categoryOptions()); }); dialog->open(); } @@ -149,6 +156,11 @@ BitTorrent::CategoryOptions TorrentCategoryDialog::categoryOptions() const else if (m_ui->comboUseDownloadPath->currentIndex() == 2) categoryOptions.downloadPath = {false, {}}; + categoryOptions.ratioLimit = m_ui->torrentShareLimitsWidget->ratioLimit().value_or(BitTorrent::DEFAULT_RATIO_LIMIT); + categoryOptions.seedingTimeLimit = m_ui->torrentShareLimitsWidget->seedingTimeLimit().value_or(BitTorrent::DEFAULT_SEEDING_TIME_LIMIT); + categoryOptions.inactiveSeedingTimeLimit = m_ui->torrentShareLimitsWidget->inactiveSeedingTimeLimit().value_or(BitTorrent::DEFAULT_SEEDING_TIME_LIMIT); + categoryOptions.shareLimitAction = m_ui->torrentShareLimitsWidget->shareLimitAction().value_or(BitTorrent::ShareLimitAction::Default); + return categoryOptions; } @@ -165,6 +177,11 @@ void TorrentCategoryDialog::setCategoryOptions(const BitTorrent::CategoryOptions m_ui->comboUseDownloadPath->setCurrentIndex(0); m_ui->comboDownloadPath->setSelectedPath({}); } + + m_ui->torrentShareLimitsWidget->setRatioLimit(categoryOptions.ratioLimit); + m_ui->torrentShareLimitsWidget->setSeedingTimeLimit(categoryOptions.seedingTimeLimit); + m_ui->torrentShareLimitsWidget->setInactiveSeedingTimeLimit(categoryOptions.inactiveSeedingTimeLimit); + m_ui->torrentShareLimitsWidget->setShareLimitAction(categoryOptions.shareLimitAction); } void TorrentCategoryDialog::categoryNameChanged(const QString &categoryName) @@ -177,6 +194,13 @@ void TorrentCategoryDialog::categoryNameChanged(const QString &categoryName) if (useDownloadPath) m_ui->comboDownloadPath->setPlaceholder(btSession->categoryDownloadPath(categoryName, categoryOptions())); + const QString parentCategoryName = BitTorrent::Session::parentCategoryName(categoryName); + if (m_parentCategoryName != parentCategoryName) + { + m_parentCategoryName = parentCategoryName; + resetShareLimitsWidgetDefaults(); + } + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!categoryName.isEmpty()); } @@ -195,3 +219,11 @@ void TorrentCategoryDialog::useDownloadPathChanged(const int index) const Path categoryPath = btSession->categoryDownloadPath(categoryName, categoryOptions()); m_ui->comboDownloadPath->setPlaceholder(useDownloadPath ? categoryPath : Path()); } + +void TorrentCategoryDialog::resetShareLimitsWidgetDefaults() +{ + const auto *btSession = BitTorrent::Session::instance(); + m_ui->torrentShareLimitsWidget->setDefaults((m_parentCategoryName.isEmpty() ? TorrentShareLimitsWidget::UsedDefaults::Global : TorrentShareLimitsWidget::UsedDefaults::Category) + , btSession->categoryRatioLimit(m_parentCategoryName), btSession->categorySeedingTimeLimit(m_parentCategoryName) + , btSession->categoryInactiveSeedingTimeLimit(m_parentCategoryName), btSession->categoryShareLimitAction(m_parentCategoryName)); +} diff --git a/src/gui/torrentcategorydialog.h b/src/gui/torrentcategorydialog.h index 6a1e315a8..ec711f5ad 100644 --- a/src/gui/torrentcategorydialog.h +++ b/src/gui/torrentcategorydialog.h @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017, 2021 Vladimir Golovnev + * Copyright (C) 2017-2025 Vladimir Golovnev * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -52,6 +52,7 @@ public: static void editCategory(QWidget *parent, const QString &categoryName); explicit TorrentCategoryDialog(QWidget *parent = nullptr); + TorrentCategoryDialog(QWidget *parent, const QString &categoryName, const BitTorrent::CategoryOptions &categoryOptions); ~TorrentCategoryDialog() override; void setCategoryNameEditable(bool editable); @@ -65,6 +66,9 @@ private slots: void useDownloadPathChanged(int index); private: + void resetShareLimitsWidgetDefaults(); + Ui::TorrentCategoryDialog *m_ui = nullptr; Path m_lastEnteredDownloadPath; + QString m_parentCategoryName; }; diff --git a/src/gui/torrentcategorydialog.ui b/src/gui/torrentcategorydialog.ui index 804af09dd..f1f5015e8 100644 --- a/src/gui/torrentcategorydialog.ui +++ b/src/gui/torrentcategorydialog.ui @@ -7,7 +7,7 @@ 0 0 493 - 208 + 268 @@ -140,6 +140,18 @@ + + + + Torrent share limits + + + + + + + + @@ -172,6 +184,12 @@
gui/fspathedit.h
1 + + TorrentShareLimitsWidget + QWidget +
gui/torrentsharelimitswidget.h
+ 1 +
diff --git a/src/gui/torrentcreatordialog.cpp b/src/gui/torrentcreatordialog.cpp index a7a1159f7..fbb32e1d2 100644 --- a/src/gui/torrentcreatordialog.cpp +++ b/src/gui/torrentcreatordialog.cpp @@ -347,9 +347,9 @@ void TorrentCreatorDialog::handleCreationSuccess(const BitTorrent::TorrentCreato params.skipChecking = true; if (m_ui->checkIgnoreShareLimits->isChecked()) { - params.ratioLimit = BitTorrent::Torrent::NO_RATIO_LIMIT; - params.seedingTimeLimit = BitTorrent::Torrent::NO_SEEDING_TIME_LIMIT; - params.inactiveSeedingTimeLimit = BitTorrent::Torrent::NO_INACTIVE_SEEDING_TIME_LIMIT; + params.ratioLimit = BitTorrent::NO_RATIO_LIMIT; + params.seedingTimeLimit = BitTorrent::NO_SEEDING_TIME_LIMIT; + params.inactiveSeedingTimeLimit = BitTorrent::NO_SEEDING_TIME_LIMIT; } params.useAutoTMM = false; // otherwise if it is on by default, it will overwrite `savePath` to the default save path diff --git a/src/gui/torrentoptionsdialog.cpp b/src/gui/torrentoptionsdialog.cpp index be35440b3..15a0a83bb 100644 --- a/src/gui/torrentoptionsdialog.cpp +++ b/src/gui/torrentoptionsdialog.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2024 Vladimir Golovnev + * Copyright (C) 2024-2025 Vladimir Golovnev * Copyright (C) 2020 thalieht * Copyright (C) 2011 Christian Kandeler * Copyright (C) 2011 Christophe Dumez @@ -289,7 +289,12 @@ TorrentOptionsDialog::TorrentOptionsDialog(QWidget *parent, const QListtorrentShareLimitsWidget->setDefaultLimits(session->globalMaxRatio(), session->globalMaxSeedingMinutes(), session->globalMaxInactiveSeedingMinutes()); + if (m_allSameCategory) + { + m_ui->torrentShareLimitsWidget->setDefaults((firstTorrentCategory.isEmpty() ? TorrentShareLimitsWidget::UsedDefaults::Global : TorrentShareLimitsWidget::UsedDefaults::Category) + , session->categoryRatioLimit(firstTorrentCategory), session->categorySeedingTimeLimit(firstTorrentCategory) + , session->categoryInactiveSeedingTimeLimit(firstTorrentCategory), session->categoryShareLimitAction(firstTorrentCategory)); + } if (allSameRatio) m_ui->torrentShareLimitsWidget->setRatioLimit(firstTorrentRatio); if (allSameSeedingTime) @@ -477,30 +482,37 @@ void TorrentOptionsDialog::accept() void TorrentOptionsDialog::handleCategoryChanged([[maybe_unused]] const int index) { - if (m_ui->checkAutoTMM->checkState() == Qt::Checked) - { - if (!m_allSameCategory && (m_ui->comboCategory->currentIndex() == 0)) - { - m_ui->savePath->setSelectedPath({}); - } - else - { - const Path savePath = BitTorrent::Session::instance()->categorySavePath(m_ui->comboCategory->currentText()); - m_ui->savePath->setSelectedPath(savePath); - const Path downloadPath = BitTorrent::Session::instance()->categoryDownloadPath(m_ui->comboCategory->currentText()); - m_ui->downloadPath->setSelectedPath(downloadPath); - m_ui->checkUseDownloadPath->setChecked(!downloadPath.isEmpty()); - } - } + const auto *btSession = BitTorrent::Session::instance(); if (!m_allSameCategory && (m_ui->comboCategory->currentIndex() == 0)) { + if (m_ui->checkAutoTMM->checkState() == Qt::Checked) + m_ui->savePath->setSelectedPath({}); + m_ui->comboCategory->clearEditText(); m_ui->comboCategory->lineEdit()->setPlaceholderText(m_currentCategoriesString); + + m_ui->torrentShareLimitsWidget->setDefaults(TorrentShareLimitsWidget::UsedDefaults::Global + , BitTorrent::DEFAULT_RATIO_LIMIT, BitTorrent::DEFAULT_SEEDING_TIME_LIMIT + , BitTorrent::DEFAULT_SEEDING_TIME_LIMIT, BitTorrent::ShareLimitAction::Default); } else { + const QString categoryName = m_ui->comboCategory->currentText(); + + if (m_ui->checkAutoTMM->checkState() == Qt::Checked) + { + const Path savePath = btSession->categorySavePath(categoryName); + m_ui->savePath->setSelectedPath(savePath); + const Path downloadPath = btSession->categoryDownloadPath(categoryName); + m_ui->downloadPath->setSelectedPath(downloadPath); + m_ui->checkUseDownloadPath->setChecked(!downloadPath.isEmpty()); + } + m_ui->comboCategory->lineEdit()->setPlaceholderText(QString()); + m_ui->torrentShareLimitsWidget->setDefaults((categoryName.isEmpty() ? TorrentShareLimitsWidget::UsedDefaults::Global : TorrentShareLimitsWidget::UsedDefaults::Category) + , btSession->categoryRatioLimit(categoryName), btSession->categorySeedingTimeLimit(categoryName) + , btSession->categoryInactiveSeedingTimeLimit(categoryName), btSession->categoryShareLimitAction(categoryName)); } } diff --git a/src/gui/torrentoptionsdialog.h b/src/gui/torrentoptionsdialog.h index 25accf3db..d2be8afbf 100644 --- a/src/gui/torrentoptionsdialog.h +++ b/src/gui/torrentoptionsdialog.h @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2024 Vladimir Golovnev + * Copyright (C) 2024-2025 Vladimir Golovnev * Copyright (C) 2020 thalieht * Copyright (C) 2011 Christian Kandeler * Copyright (C) 2011 Christophe Dumez @@ -35,7 +35,7 @@ #include -#include "base/bittorrent/sharelimitaction.h" +#include "base/bittorrent/sharelimits.h" #include "base/path.h" #include "base/settingvalue.h" diff --git a/src/gui/torrentsharelimitswidget.cpp b/src/gui/torrentsharelimitswidget.cpp index 3ee898e69..ca3f9ab8d 100644 --- a/src/gui/torrentsharelimitswidget.cpp +++ b/src/gui/torrentsharelimitswidget.cpp @@ -52,6 +52,29 @@ namespace RemoveWithContentActionIndex, SuperSeedingActionIndex }; + + QString shareLimitActionName(const BitTorrent::ShareLimitAction shareLimitAction) + { + switch (shareLimitAction) + { + case BitTorrent::ShareLimitAction::Stop: + return TorrentShareLimitsWidget::tr("Stop torrent"); + + case BitTorrent::ShareLimitAction::Remove: + return TorrentShareLimitsWidget::tr("Remove torrent"); + + case BitTorrent::ShareLimitAction::RemoveWithContent: + return TorrentShareLimitsWidget::tr("Remove torrent and its content"); + + case BitTorrent::ShareLimitAction::EnableSuperSeeding: + return TorrentShareLimitsWidget::tr("Enable super seeding for torrent"); + + case BitTorrent::ShareLimitAction::Default: + return TorrentShareLimitsWidget::tr("Default"); + } + + return {}; + } } TorrentShareLimitsWidget::TorrentShareLimitsWidget(QWidget *parent) @@ -60,6 +83,30 @@ TorrentShareLimitsWidget::TorrentShareLimitsWidget(QWidget *parent) { m_ui->setupUi(this); + m_ui->comboBoxRatioMode->addItem({}); + m_ui->comboBoxRatioMode->addItem(tr("Unlimited")); + m_ui->comboBoxRatioMode->addItem(tr("Set to")); + m_ui->comboBoxRatioMode->setCurrentIndex(UninitializedModeIndex); + + m_ui->comboBoxSeedingTimeMode->addItem({}); + m_ui->comboBoxSeedingTimeMode->addItem(tr("Unlimited")); + m_ui->comboBoxSeedingTimeMode->addItem(tr("Set to")); + m_ui->comboBoxSeedingTimeMode->setCurrentIndex(UninitializedModeIndex); + + m_ui->comboBoxInactiveSeedingTimeMode->addItem({}); + m_ui->comboBoxInactiveSeedingTimeMode->addItem(tr("Unlimited")); + m_ui->comboBoxInactiveSeedingTimeMode->addItem(tr("Set to")); + m_ui->comboBoxInactiveSeedingTimeMode->setCurrentIndex(UninitializedModeIndex); + + m_ui->comboBoxAction->addItem({}); + m_ui->comboBoxAction->addItem(shareLimitActionName(BitTorrent::ShareLimitAction::Stop)); + m_ui->comboBoxAction->addItem(shareLimitActionName(BitTorrent::ShareLimitAction::Remove)); + m_ui->comboBoxAction->addItem(shareLimitActionName(BitTorrent::ShareLimitAction::RemoveWithContent)); + m_ui->comboBoxAction->addItem(shareLimitActionName(BitTorrent::ShareLimitAction::EnableSuperSeeding)); + m_ui->comboBoxAction->setCurrentIndex(UninitializedActionIndex); + + resetDefaultItemsText(); + m_ui->spinBoxRatioValue->setEnabled(false); m_ui->spinBoxRatioValue->setMaximum(std::numeric_limits::max()); m_ui->spinBoxRatioValue->setSuffix({}); @@ -71,9 +118,25 @@ TorrentShareLimitsWidget::TorrentShareLimitsWidget(QWidget *parent) m_ui->spinBoxInactiveSeedingTimeValue->setSuffix({}); m_ui->spinBoxInactiveSeedingTimeValue->clear(); - connect(m_ui->comboBoxRatioMode, &QComboBox::currentIndexChanged, this, &TorrentShareLimitsWidget::refreshRatioLimitControls); - connect(m_ui->comboBoxSeedingTimeMode, &QComboBox::currentIndexChanged, this, &TorrentShareLimitsWidget::refreshSeedingTimeLimitControls); - connect(m_ui->comboBoxInactiveSeedingTimeMode, &QComboBox::currentIndexChanged, this, &TorrentShareLimitsWidget::refreshInactiveSeedingTimeLimitControls); + int prevIndex = UninitializedModeIndex; + connect(m_ui->comboBoxRatioMode, &QComboBox::currentIndexChanged, this + , [this, prevIndex](const int currentIndex) mutable + { + onRatioLimitModeChanged(currentIndex, prevIndex); + prevIndex = currentIndex; + }); + connect(m_ui->comboBoxSeedingTimeMode, &QComboBox::currentIndexChanged, this + , [this, prevIndex](const int currentIndex) mutable + { + onSeedingTimeLimitModeChanged(currentIndex, prevIndex); + prevIndex = currentIndex; + }); + connect(m_ui->comboBoxInactiveSeedingTimeMode, &QComboBox::currentIndexChanged, this + , [this, prevIndex](const int currentIndex) mutable + { + onInactiveSeedingTimeLimitModeChanged(currentIndex, prevIndex); + prevIndex = currentIndex; + }); } TorrentShareLimitsWidget::~TorrentShareLimitsWidget() @@ -83,11 +146,11 @@ TorrentShareLimitsWidget::~TorrentShareLimitsWidget() void TorrentShareLimitsWidget::setRatioLimit(const qreal ratioLimit) { - if (ratioLimit == BitTorrent::Torrent::USE_GLOBAL_RATIO) + if (ratioLimit == BitTorrent::DEFAULT_RATIO_LIMIT) { m_ui->comboBoxRatioMode->setCurrentIndex(DefaultModeIndex); } - else if (ratioLimit == BitTorrent::Torrent::NO_RATIO_LIMIT) + else if (ratioLimit == BitTorrent::NO_RATIO_LIMIT) { m_ui->comboBoxRatioMode->setCurrentIndex(UnlimitedModeIndex); } @@ -100,11 +163,11 @@ void TorrentShareLimitsWidget::setRatioLimit(const qreal ratioLimit) void TorrentShareLimitsWidget::setSeedingTimeLimit(const int seedingTimeLimit) { - if (seedingTimeLimit == BitTorrent::Torrent::USE_GLOBAL_SEEDING_TIME) + if (seedingTimeLimit == BitTorrent::DEFAULT_SEEDING_TIME_LIMIT) { m_ui->comboBoxSeedingTimeMode->setCurrentIndex(DefaultModeIndex); } - else if (seedingTimeLimit == BitTorrent::Torrent::NO_SEEDING_TIME_LIMIT) + else if (seedingTimeLimit == BitTorrent::NO_SEEDING_TIME_LIMIT) { m_ui->comboBoxSeedingTimeMode->setCurrentIndex(UnlimitedModeIndex); } @@ -117,11 +180,11 @@ void TorrentShareLimitsWidget::setSeedingTimeLimit(const int seedingTimeLimit) void TorrentShareLimitsWidget::setInactiveSeedingTimeLimit(const int inactiveSeedingTimeLimit) { - if (inactiveSeedingTimeLimit == BitTorrent::Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME) + if (inactiveSeedingTimeLimit == BitTorrent::DEFAULT_SEEDING_TIME_LIMIT) { m_ui->comboBoxInactiveSeedingTimeMode->setCurrentIndex(DefaultModeIndex); } - else if (inactiveSeedingTimeLimit == BitTorrent::Torrent::NO_INACTIVE_SEEDING_TIME_LIMIT) + else if (inactiveSeedingTimeLimit == BitTorrent::NO_SEEDING_TIME_LIMIT) { m_ui->comboBoxInactiveSeedingTimeMode->setCurrentIndex(UnlimitedModeIndex); } @@ -155,25 +218,56 @@ void TorrentShareLimitsWidget::setShareLimitAction(const BitTorrent::ShareLimitA } } -void TorrentShareLimitsWidget::setDefaultLimits(const qreal ratioLimit, const int seedingTimeLimit, const int inactiveSeedingTimeLimit) +void TorrentShareLimitsWidget::setDefaults(UsedDefaults usedDefaults + , const qreal ratioLimit, const int seedingTimeLimit + , const int inactiveSeedingTimeLimit, const BitTorrent::ShareLimitAction action) { - if (m_defaultRatioLimit != ratioLimit) + m_defaultRatioLimit = ratioLimit; + if (m_ui->comboBoxRatioMode->currentIndex() == DefaultModeIndex) { - m_defaultRatioLimit = ratioLimit; - refreshRatioLimitControls(); + if (m_defaultRatioLimit >= 0) + { + m_ui->spinBoxRatioValue->setValue(m_defaultRatioLimit); + } + else + { + m_ui->spinBoxRatioValue->clear(); + } } - if (m_defaultSeedingTimeLimit != seedingTimeLimit) + m_defaultSeedingTimeLimit = seedingTimeLimit; + if (m_ui->comboBoxSeedingTimeMode->currentIndex() == DefaultModeIndex) { - m_defaultSeedingTimeLimit = seedingTimeLimit; - refreshSeedingTimeLimitControls(); + if (m_defaultSeedingTimeLimit >= 0) + { + m_ui->spinBoxSeedingTimeValue->setValue(m_defaultSeedingTimeLimit); + m_ui->spinBoxSeedingTimeValue->setSuffix(tr(" min")); + } + else + { + m_ui->spinBoxSeedingTimeValue->setSuffix({}); + m_ui->spinBoxSeedingTimeValue->clear(); + } } - if (m_defaultInactiveSeedingTimeLimit != inactiveSeedingTimeLimit) + m_defaultInactiveSeedingTimeLimit = inactiveSeedingTimeLimit; + if (m_ui->comboBoxInactiveSeedingTimeMode->currentIndex() == DefaultModeIndex) { - m_defaultInactiveSeedingTimeLimit = inactiveSeedingTimeLimit; - refreshInactiveSeedingTimeLimitControls(); + if (m_defaultInactiveSeedingTimeLimit >= 0) + { + m_ui->spinBoxInactiveSeedingTimeValue->setValue(m_defaultInactiveSeedingTimeLimit); + m_ui->spinBoxInactiveSeedingTimeValue->setSuffix(tr(" min")); + } + else + { + m_ui->spinBoxInactiveSeedingTimeValue->setSuffix({}); + m_ui->spinBoxInactiveSeedingTimeValue->clear(); + } } + + m_defaultShareLimitAction = action; + m_usedDefaults = usedDefaults; + resetDefaultItemsText(); } std::optional TorrentShareLimitsWidget::ratioLimit() const @@ -181,9 +275,9 @@ std::optional TorrentShareLimitsWidget::ratioLimit() const switch (m_ui->comboBoxRatioMode->currentIndex()) { case DefaultModeIndex: - return BitTorrent::Torrent::USE_GLOBAL_RATIO; + return BitTorrent::DEFAULT_RATIO_LIMIT; case UnlimitedModeIndex: - return BitTorrent::Torrent::NO_RATIO_LIMIT; + return BitTorrent::NO_RATIO_LIMIT; case AssignedModeIndex: return m_ui->spinBoxRatioValue->value(); default: @@ -196,9 +290,9 @@ std::optional TorrentShareLimitsWidget::seedingTimeLimit() const switch (m_ui->comboBoxSeedingTimeMode->currentIndex()) { case DefaultModeIndex: - return BitTorrent::Torrent::USE_GLOBAL_SEEDING_TIME; + return BitTorrent::DEFAULT_SEEDING_TIME_LIMIT; case UnlimitedModeIndex: - return BitTorrent::Torrent::NO_SEEDING_TIME_LIMIT; + return BitTorrent::NO_SEEDING_TIME_LIMIT; case AssignedModeIndex: return m_ui->spinBoxSeedingTimeValue->value(); default: @@ -211,9 +305,9 @@ std::optional TorrentShareLimitsWidget::inactiveSeedingTimeLimit() const switch (m_ui->comboBoxInactiveSeedingTimeMode->currentIndex()) { case DefaultModeIndex: - return BitTorrent::Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME; + return BitTorrent::DEFAULT_SEEDING_TIME_LIMIT; case UnlimitedModeIndex: - return BitTorrent::Torrent::NO_INACTIVE_SEEDING_TIME_LIMIT; + return BitTorrent::NO_SEEDING_TIME_LIMIT; case AssignedModeIndex: return m_ui->spinBoxInactiveSeedingTimeValue->value(); default: @@ -240,68 +334,97 @@ std::optional TorrentShareLimitsWidget::shareLimit } } -void TorrentShareLimitsWidget::refreshRatioLimitControls() +void TorrentShareLimitsWidget::onRatioLimitModeChanged(const int currentIndex, const int previousIndex) { - const auto index = m_ui->comboBoxRatioMode->currentIndex(); + m_ui->spinBoxRatioValue->setEnabled(currentIndex == AssignedModeIndex); - m_ui->spinBoxRatioValue->setEnabled(index == AssignedModeIndex); - if (index == AssignedModeIndex) + if (previousIndex == AssignedModeIndex) + m_ratioLimit = m_ui->spinBoxRatioValue->value(); + + if (currentIndex == AssignedModeIndex) { m_ui->spinBoxRatioValue->setValue(m_ratioLimit); } - else if ((index == DefaultModeIndex) && (m_defaultRatioLimit >= 0)) + else if ((currentIndex == DefaultModeIndex) && (m_defaultRatioLimit >= 0)) { m_ui->spinBoxRatioValue->setValue(m_defaultRatioLimit); } else { - m_ratioLimit = m_ui->spinBoxRatioValue->value(); m_ui->spinBoxRatioValue->clear(); } } -void TorrentShareLimitsWidget::refreshSeedingTimeLimitControls() +void TorrentShareLimitsWidget::onSeedingTimeLimitModeChanged(const int currentIndex, const int previousIndex) { - const auto index = m_ui->comboBoxSeedingTimeMode->currentIndex(); + m_ui->spinBoxSeedingTimeValue->setEnabled(currentIndex == AssignedModeIndex); - m_ui->spinBoxSeedingTimeValue->setEnabled(index == AssignedModeIndex); - if (index == AssignedModeIndex) + if (previousIndex == AssignedModeIndex) + m_seedingTimeLimit = m_ui->spinBoxSeedingTimeValue->value(); + + if (currentIndex == AssignedModeIndex) { m_ui->spinBoxSeedingTimeValue->setValue(m_seedingTimeLimit); m_ui->spinBoxSeedingTimeValue->setSuffix(tr(" min")); } - else if ((index == DefaultModeIndex) && (m_defaultSeedingTimeLimit >= 0)) + else if ((currentIndex == DefaultModeIndex) && (m_defaultSeedingTimeLimit >= 0)) { m_ui->spinBoxSeedingTimeValue->setValue(m_defaultSeedingTimeLimit); m_ui->spinBoxSeedingTimeValue->setSuffix(tr(" min")); } else { - m_seedingTimeLimit = m_ui->spinBoxSeedingTimeValue->value(); m_ui->spinBoxSeedingTimeValue->setSuffix({}); m_ui->spinBoxSeedingTimeValue->clear(); } } -void TorrentShareLimitsWidget::refreshInactiveSeedingTimeLimitControls() +void TorrentShareLimitsWidget::onInactiveSeedingTimeLimitModeChanged(const int currentIndex, const int previousIndex) { - const auto index = m_ui->comboBoxInactiveSeedingTimeMode->currentIndex(); + m_ui->spinBoxInactiveSeedingTimeValue->setEnabled(currentIndex == AssignedModeIndex); - m_ui->spinBoxInactiveSeedingTimeValue->setEnabled(index == AssignedModeIndex); - if (index == AssignedModeIndex) + if (previousIndex == AssignedModeIndex) + m_inactiveSeedingTimeLimit = m_ui->spinBoxInactiveSeedingTimeValue->value(); + + if (currentIndex == AssignedModeIndex) { m_ui->spinBoxInactiveSeedingTimeValue->setValue(m_inactiveSeedingTimeLimit); m_ui->spinBoxInactiveSeedingTimeValue->setSuffix(tr(" min")); } - else if ((index == DefaultModeIndex) && (m_defaultInactiveSeedingTimeLimit >= 0)) + else if ((currentIndex == DefaultModeIndex) && (m_defaultInactiveSeedingTimeLimit >= 0)) { m_ui->spinBoxInactiveSeedingTimeValue->setValue(m_defaultInactiveSeedingTimeLimit); m_ui->spinBoxInactiveSeedingTimeValue->setSuffix(tr(" min")); } else { - m_inactiveSeedingTimeLimit = m_ui->spinBoxInactiveSeedingTimeValue->value(); m_ui->spinBoxInactiveSeedingTimeValue->setSuffix({}); m_ui->spinBoxInactiveSeedingTimeValue->clear(); } } + +void TorrentShareLimitsWidget::resetDefaultItemsText() +{ + if (m_usedDefaults == UsedDefaults::Global) + { + m_ui->comboBoxRatioMode->setItemText(DefaultModeIndex, tr("Default")); + m_ui->comboBoxSeedingTimeMode->setItemText(DefaultModeIndex, tr("Default")); + m_ui->comboBoxInactiveSeedingTimeMode->setItemText(DefaultModeIndex, tr("Default")); + + m_ui->comboBoxAction->setItemText(DefaultActionIndex + , (m_defaultShareLimitAction == BitTorrent::ShareLimitAction::Default) + ? tr("Default") + : tr("Default (%1)", "Default (share limit action)").arg(shareLimitActionName(m_defaultShareLimitAction))); + } + else // TorrentOptions + { + m_ui->comboBoxRatioMode->setItemText(DefaultModeIndex, tr("From category")); + m_ui->comboBoxSeedingTimeMode->setItemText(DefaultModeIndex, tr("From category")); + m_ui->comboBoxInactiveSeedingTimeMode->setItemText(DefaultModeIndex, tr("From category")); + + m_ui->comboBoxAction->setItemText(DefaultActionIndex + , (m_defaultShareLimitAction == BitTorrent::ShareLimitAction::Default) + ? tr("From category") + : tr("From category (%1)", "From category (share limit action)").arg(shareLimitActionName(m_defaultShareLimitAction))); + } +} diff --git a/src/gui/torrentsharelimitswidget.h b/src/gui/torrentsharelimitswidget.h index b99a830b6..cd3f405e0 100644 --- a/src/gui/torrentsharelimitswidget.h +++ b/src/gui/torrentsharelimitswidget.h @@ -32,7 +32,7 @@ #include -#include "base/bittorrent/sharelimitaction.h" +#include "base/bittorrent/sharelimits.h" namespace Ui { @@ -45,6 +45,12 @@ class TorrentShareLimitsWidget final : public QWidget Q_DISABLE_COPY_MOVE(TorrentShareLimitsWidget) public: + enum class UsedDefaults + { + Global, + Category + }; + explicit TorrentShareLimitsWidget(QWidget *parent = nullptr); ~TorrentShareLimitsWidget() override; @@ -53,7 +59,8 @@ public: void setInactiveSeedingTimeLimit(int inactiveSeedingTimeLimit); void setShareLimitAction(BitTorrent::ShareLimitAction action); - void setDefaultLimits(qreal ratioLimit, int seedingTimeLimit, int inactiveSeedingTimeLimit); + void setDefaults(UsedDefaults usedDefaults, qreal ratioLimit, int seedingTimeLimit + , int inactiveSeedingTimeLimit, BitTorrent::ShareLimitAction action); std::optional ratioLimit() const; std::optional seedingTimeLimit() const; @@ -61,9 +68,10 @@ public: std::optional shareLimitAction() const; private: - void refreshRatioLimitControls(); - void refreshSeedingTimeLimitControls(); - void refreshInactiveSeedingTimeLimitControls(); + void onRatioLimitModeChanged(int currentIndex, int previousIndex); + void onSeedingTimeLimitModeChanged(int currentIndex, int previousIndex); + void onInactiveSeedingTimeLimitModeChanged(int currentIndex, int previousIndex); + void resetDefaultItemsText(); Ui::TorrentShareLimitsWidget *m_ui = nullptr; @@ -74,4 +82,7 @@ private: int m_defaultSeedingTimeLimit = -1; int m_defaultInactiveSeedingTimeLimit = -1; qreal m_defaultRatioLimit = -1; + BitTorrent::ShareLimitAction m_defaultShareLimitAction = BitTorrent::ShareLimitAction::Default; + + UsedDefaults m_usedDefaults = UsedDefaults::Global; }; diff --git a/src/gui/torrentsharelimitswidget.ui b/src/gui/torrentsharelimitswidget.ui index 13fbfe0a2..6c822f07d 100644 --- a/src/gui/torrentsharelimitswidget.ui +++ b/src/gui/torrentsharelimitswidget.ui @@ -21,26 +21,7 @@
- - - -1 - - - - Default - - - - - Unlimited - - - - - Set to - - - + @@ -63,26 +44,7 @@ - - - -1 - - - - Default - - - - - Unlimited - - - - - Set to - - - + @@ -108,26 +70,7 @@ - - - -1 - - - - Default - - - - - Unlimited - - - - - Set to - - - + @@ -157,36 +100,7 @@ - - - -1 - - - - Default - - - - - Stop torrent - - - - - Remove torrent - - - - - Remove torrent and its content - - - - - Enable super seeding for torrent - - - + diff --git a/src/gui/transferlistmodel.cpp b/src/gui/transferlistmodel.cpp index 756046137..ba6788c27 100644 --- a/src/gui/transferlistmodel.cpp +++ b/src/gui/transferlistmodel.cpp @@ -392,7 +392,7 @@ QString TransferListModel::displayValue(const BitTorrent::Torrent *torrent, cons case TR_RATIO: return ratioString(torrent->realRatio()); case TR_RATIO_LIMIT: - return ratioString(torrent->maxRatio()); + return ratioString(torrent->effectiveRatioLimit()); case TR_POPULARITY: return ratioString(torrent->popularity()); case TR_CATEGORY: @@ -509,7 +509,7 @@ QVariant TransferListModel::internalValue(const BitTorrent::Torrent *torrent, co case TR_COMPLETED: return torrent->completedSize(); case TR_RATIO_LIMIT: - return torrent->maxRatio(); + return torrent->effectiveRatioLimit(); case TR_SEEN_COMPLETE_DATE: return torrent->lastSeenComplete(); case TR_LAST_ACTIVITY: diff --git a/src/webui/api/serialize/serialize_torrent.cpp b/src/webui/api/serialize/serialize_torrent.cpp index 1a64bd797..36c9a990c 100644 --- a/src/webui/api/serialize/serialize_torrent.cpp +++ b/src/webui/api/serialize/serialize_torrent.cpp @@ -163,9 +163,9 @@ QVariantMap serialize(const BitTorrent::Torrent &torrent) {KEY_TORRENT_AMOUNT_COMPLETED, torrent.completedSize()}, {KEY_TORRENT_CONNECTIONS_COUNT, torrent.connectionsCount()}, {KEY_TORRENT_CONNECTIONS_LIMIT, torrent.connectionsLimit()}, - {KEY_TORRENT_MAX_RATIO, torrent.maxRatio()}, - {KEY_TORRENT_MAX_SEEDING_TIME, torrent.maxSeedingTime()}, - {KEY_TORRENT_MAX_INACTIVE_SEEDING_TIME, torrent.maxInactiveSeedingTime()}, + {KEY_TORRENT_MAX_RATIO, torrent.effectiveRatioLimit()}, + {KEY_TORRENT_MAX_SEEDING_TIME, torrent.effectiveSeedingTimeLimit()}, + {KEY_TORRENT_MAX_INACTIVE_SEEDING_TIME, torrent.effectiveInactiveSeedingTimeLimit()}, {KEY_TORRENT_RATIO, adjustRatio(torrent.realRatio())}, {KEY_TORRENT_RATIO_LIMIT, torrent.ratioLimit()}, {KEY_TORRENT_POPULARITY, torrent.popularity()}, diff --git a/src/webui/api/torrentscontroller.cpp b/src/webui/api/torrentscontroller.cpp index b91f5c1da..c1cd5cdbb 100644 --- a/src/webui/api/torrentscontroller.cpp +++ b/src/webui/api/torrentscontroller.cpp @@ -1066,9 +1066,9 @@ void TorrentsController::addAction() const QString torrentName = params()[u"rename"_s].trimmed(); const int upLimit = parseInt(params()[u"upLimit"_s]).value_or(-1); const int dlLimit = parseInt(params()[u"dlLimit"_s]).value_or(-1); - const double ratioLimit = parseDouble(params()[u"ratioLimit"_s]).value_or(BitTorrent::Torrent::USE_GLOBAL_RATIO); - const int seedingTimeLimit = parseInt(params()[u"seedingTimeLimit"_s]).value_or(BitTorrent::Torrent::USE_GLOBAL_SEEDING_TIME); - const int inactiveSeedingTimeLimit = parseInt(params()[u"inactiveSeedingTimeLimit"_s]).value_or(BitTorrent::Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME); + const double ratioLimit = parseDouble(params()[u"ratioLimit"_s]).value_or(BitTorrent::DEFAULT_RATIO_LIMIT); + const int seedingTimeLimit = parseInt(params()[u"seedingTimeLimit"_s]).value_or(BitTorrent::DEFAULT_SEEDING_TIME_LIMIT); + const int inactiveSeedingTimeLimit = parseInt(params()[u"inactiveSeedingTimeLimit"_s]).value_or(BitTorrent::DEFAULT_SEEDING_TIME_LIMIT); const BitTorrent::ShareLimitAction shareLimitAction = Utils::String::toEnum(params()[u"shareLimitAction"_s], BitTorrent::ShareLimitAction::Default); const std::optional autoTMM = parseBool(params()[u"autoTMM"_s]); @@ -1897,7 +1897,7 @@ void TorrentsController::editCategoryAction() categoryOptions.downloadPath = {useDownloadPath.value(), downloadPath}; } - if (!BitTorrent::Session::instance()->editCategory(category, categoryOptions)) + if (!BitTorrent::Session::instance()->setCategoryOptions(category, categoryOptions)) throw APIError(APIErrorType::Conflict, tr("Unable to edit category")); setResult(QString());