mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2026-01-08 08:32:31 -06:00
Add option to stop seeding when torrent has been inactive
PR #19294. Closes #533. Closes #8073. Closes #15939.
This commit is contained in:
@@ -50,6 +50,7 @@ const QString PARAM_AUTOTMM = u"use_auto_tmm"_s;
|
||||
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_RATIOLIMIT = u"ratio_limit"_s;
|
||||
|
||||
namespace
|
||||
@@ -107,14 +108,14 @@ bool BitTorrent::operator==(const AddTorrentParams &lhs, const AddTorrentParams
|
||||
lhs.addToQueueTop, lhs.addPaused, lhs.stopCondition,
|
||||
lhs.filePaths, lhs.filePriorities, lhs.skipChecking,
|
||||
lhs.contentLayout, lhs.useAutoTMM, lhs.uploadLimit,
|
||||
lhs.downloadLimit, lhs.seedingTimeLimit, lhs.ratioLimit)
|
||||
lhs.downloadLimit, lhs.seedingTimeLimit, lhs.inactiveSeedingTimeLimit, lhs.ratioLimit)
|
||||
== std::tie(rhs.name, rhs.category, rhs.tags,
|
||||
rhs.savePath, rhs.useDownloadPath, rhs.downloadPath,
|
||||
rhs.sequential, rhs.firstLastPiecePriority, rhs.addForced,
|
||||
rhs.addToQueueTop, rhs.addPaused, rhs.stopCondition,
|
||||
rhs.filePaths, rhs.filePriorities, rhs.skipChecking,
|
||||
rhs.contentLayout, rhs.useAutoTMM, rhs.uploadLimit,
|
||||
rhs.downloadLimit, rhs.seedingTimeLimit, rhs.ratioLimit);
|
||||
rhs.downloadLimit, rhs.seedingTimeLimit, rhs.inactiveSeedingTimeLimit, rhs.ratioLimit);
|
||||
}
|
||||
|
||||
BitTorrent::AddTorrentParams BitTorrent::parseAddTorrentParams(const QJsonObject &jsonObj)
|
||||
@@ -134,6 +135,7 @@ BitTorrent::AddTorrentParams BitTorrent::parseAddTorrentParams(const QJsonObject
|
||||
params.uploadLimit = jsonObj.value(PARAM_UPLOADLIMIT).toInt(-1);
|
||||
params.downloadLimit = jsonObj.value(PARAM_DOWNLOADLIMIT).toInt(-1);
|
||||
params.seedingTimeLimit = jsonObj.value(PARAM_SEEDINGTIMELIMIT).toInt(BitTorrent::Torrent::USE_GLOBAL_SEEDING_TIME);
|
||||
params.inactiveSeedingTimeLimit = jsonObj.value(PARAM_INACTIVESEEDINGTIMELIMIT).toInt(BitTorrent::Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME);
|
||||
params.ratioLimit = jsonObj.value(PARAM_RATIOLIMIT).toDouble(BitTorrent::Torrent::USE_GLOBAL_RATIO);
|
||||
|
||||
return params;
|
||||
@@ -152,6 +154,7 @@ QJsonObject BitTorrent::serializeAddTorrentParams(const AddTorrentParams ¶ms
|
||||
{PARAM_UPLOADLIMIT, params.uploadLimit},
|
||||
{PARAM_DOWNLOADLIMIT, params.downloadLimit},
|
||||
{PARAM_SEEDINGTIMELIMIT, params.seedingTimeLimit},
|
||||
{PARAM_INACTIVESEEDINGTIMELIMIT, params.inactiveSeedingTimeLimit},
|
||||
{PARAM_RATIOLIMIT, params.ratioLimit}
|
||||
};
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ namespace BitTorrent
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
@@ -219,6 +219,7 @@ BitTorrent::LoadResumeDataResult BitTorrent::BencodeResumeDataStorage::loadTorre
|
||||
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.savePath = Profile::instance()->fromPortablePath(
|
||||
Path(fromLTString(resumeDataRoot.dict_find_string_value("qBt-savePath"))));
|
||||
@@ -389,6 +390,7 @@ 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-category"] = resumeData.category.toStdString();
|
||||
data["qBt-tags"] = setToEntryList(resumeData.tags);
|
||||
data["qBt-name"] = resumeData.name.toStdString();
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace
|
||||
{
|
||||
const QString DB_CONNECTION_NAME = u"ResumeDataStorage"_s;
|
||||
|
||||
const int DB_VERSION = 4;
|
||||
const int DB_VERSION = 5;
|
||||
|
||||
const QString DB_TABLE_META = u"meta"_s;
|
||||
const QString DB_TABLE_TORRENTS = u"torrents"_s;
|
||||
@@ -135,6 +135,7 @@ namespace
|
||||
const Column DB_COLUMN_CONTENT_LAYOUT = makeColumn("content_layout");
|
||||
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_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");
|
||||
@@ -228,6 +229,7 @@ namespace
|
||||
resumeData.firstLastPiecePriority = query.value(DB_COLUMN_HAS_OUTER_PIECES_PRIORITY.name).toBool();
|
||||
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.contentLayout = Utils::String::toEnum<TorrentContentLayout>(
|
||||
query.value(DB_COLUMN_CONTENT_LAYOUT.name).toString(), TorrentContentLayout::Original);
|
||||
resumeData.operatingMode = Utils::String::toEnum<TorrentOperatingMode>(
|
||||
@@ -527,6 +529,7 @@ void BitTorrent::DBResumeDataStorage::createDB() const
|
||||
makeColumnDefinition(DB_COLUMN_CONTENT_LAYOUT, "TEXT NOT NULL"),
|
||||
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_HAS_OUTER_PIECES_PRIORITY, "INTEGER NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_HAS_SEED_STATUS, "INTEGER NOT NULL"),
|
||||
makeColumnDefinition(DB_COLUMN_OPERATING_MODE, "TEXT NOT NULL"),
|
||||
@@ -606,6 +609,14 @@ void BitTorrent::DBResumeDataStorage::updateDB(const int fromVersion) const
|
||||
throw RuntimeError(query.lastError().text());
|
||||
}
|
||||
|
||||
if (fromVersion <= 4)
|
||||
{
|
||||
const auto alterTableTorrentsQuery = u"ALTER TABLE %1 ADD %2"_s
|
||||
.arg(quoted(DB_TABLE_TORRENTS), makeColumnDefinition(DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT, "INTEGER NOT NULL"));
|
||||
if (!query.exec(alterTableTorrentsQuery))
|
||||
throw RuntimeError(query.lastError().text());
|
||||
}
|
||||
|
||||
const QString updateMetaVersionQuery = makeUpdateStatement(DB_TABLE_META, {DB_COLUMN_NAME, DB_COLUMN_VALUE});
|
||||
if (!query.prepare(updateMetaVersionQuery))
|
||||
throw RuntimeError(query.lastError().text());
|
||||
@@ -782,6 +793,7 @@ namespace
|
||||
DB_COLUMN_CONTENT_LAYOUT,
|
||||
DB_COLUMN_RATIO_LIMIT,
|
||||
DB_COLUMN_SEEDING_TIME_LIMIT,
|
||||
DB_COLUMN_INACTIVE_SEEDING_TIME_LIMIT,
|
||||
DB_COLUMN_HAS_OUTER_PIECES_PRIORITY,
|
||||
DB_COLUMN_HAS_SEED_STATUS,
|
||||
DB_COLUMN_OPERATING_MODE,
|
||||
@@ -840,6 +852,7 @@ namespace
|
||||
query.bindValue(DB_COLUMN_CONTENT_LAYOUT.placeholder, Utils::String::fromEnum(m_resumeData.contentLayout));
|
||||
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_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));
|
||||
|
||||
@@ -60,5 +60,6 @@ namespace BitTorrent
|
||||
|
||||
qreal ratioLimit = Torrent::USE_GLOBAL_RATIO;
|
||||
int seedingTimeLimit = Torrent::USE_GLOBAL_SEEDING_TIME;
|
||||
int inactiveSeedingTimeLimit = Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -203,6 +203,8 @@ namespace BitTorrent
|
||||
virtual void setGlobalMaxRatio(qreal ratio) = 0;
|
||||
virtual int globalMaxSeedingMinutes() const = 0;
|
||||
virtual void setGlobalMaxSeedingMinutes(int minutes) = 0;
|
||||
virtual int globalMaxInactiveSeedingMinutes() const = 0;
|
||||
virtual void setGlobalMaxInactiveSeedingMinutes(int minutes) = 0;
|
||||
virtual bool isDHTEnabled() const = 0;
|
||||
virtual void setDHTEnabled(bool enabled) = 0;
|
||||
virtual bool isLSDEnabled() const = 0;
|
||||
|
||||
@@ -474,6 +474,7 @@ SessionImpl::SessionImpl(QObject *parent)
|
||||
, m_additionalTrackers(BITTORRENT_SESSION_KEY(u"AdditionalTrackers"_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), -1, lowerLimited(-1))
|
||||
, m_globalMaxInactiveSeedingMinutes(BITTORRENT_SESSION_KEY(u"GlobalMaxInactiveSeedingMinutes"_s), -1, lowerLimited(-1))
|
||||
, m_isAddTorrentToQueueTop(BITTORRENT_SESSION_KEY(u"AddTorrentToTopOfQueue"_s), false)
|
||||
, m_isAddTorrentPaused(BITTORRENT_SESSION_KEY(u"AddTorrentPaused"_s), false)
|
||||
, m_torrentStopCondition(BITTORRENT_SESSION_KEY(u"TorrentStopCondition"_s), Torrent::StopCondition::None)
|
||||
@@ -1118,6 +1119,22 @@ void SessionImpl::setGlobalMaxSeedingMinutes(int minutes)
|
||||
}
|
||||
}
|
||||
|
||||
int SessionImpl::globalMaxInactiveSeedingMinutes() const
|
||||
{
|
||||
return m_globalMaxInactiveSeedingMinutes;
|
||||
}
|
||||
|
||||
void SessionImpl::setGlobalMaxInactiveSeedingMinutes(int minutes)
|
||||
{
|
||||
minutes = std::max(minutes, -1);
|
||||
|
||||
if (minutes != globalMaxInactiveSeedingMinutes())
|
||||
{
|
||||
m_globalMaxInactiveSeedingMinutes = minutes;
|
||||
updateSeedingLimitTimer();
|
||||
}
|
||||
}
|
||||
|
||||
void SessionImpl::applyBandwidthLimits()
|
||||
{
|
||||
lt::settings_pack settingsPack;
|
||||
@@ -2213,6 +2230,47 @@ void SessionImpl::processShareLimits()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (torrent->inactiveSeedingTimeLimit() != Torrent::NO_INACTIVE_SEEDING_TIME_LIMIT)
|
||||
{
|
||||
const qlonglong inactiveSeedingTimeInMinutes = torrent->timeSinceActivity() / 60;
|
||||
int inactiveSeedingTimeLimit = torrent->inactiveSeedingTimeLimit();
|
||||
if (inactiveSeedingTimeLimit == Torrent::USE_GLOBAL_INACTIVE_SEEDING_TIME)
|
||||
{
|
||||
// If Global Seeding Time Limit is really set...
|
||||
inactiveSeedingTimeLimit = globalMaxInactiveSeedingMinutes();
|
||||
}
|
||||
|
||||
if (inactiveSeedingTimeLimit >= 0)
|
||||
{
|
||||
if ((inactiveSeedingTimeInMinutes <= Torrent::MAX_INACTIVE_SEEDING_TIME) && (inactiveSeedingTimeInMinutes >= inactiveSeedingTimeLimit))
|
||||
{
|
||||
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(torrent->id());
|
||||
}
|
||||
else if (m_maxRatioAction == DeleteFiles)
|
||||
{
|
||||
LogMsg(u"%1 %2 %3"_s.arg(description, tr("Removed torrent and deleted its content."), torrentName));
|
||||
deleteTorrent(torrent->id(), 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4842,7 +4900,8 @@ bool SessionImpl::isKnownTorrent(const InfoHash &infoHash) const
|
||||
void SessionImpl::updateSeedingLimitTimer()
|
||||
{
|
||||
if ((globalMaxRatio() == Torrent::NO_RATIO_LIMIT) && !hasPerTorrentRatioLimit()
|
||||
&& (globalMaxSeedingMinutes() == Torrent::NO_SEEDING_TIME_LIMIT) && !hasPerTorrentSeedingTimeLimit())
|
||||
&& (globalMaxSeedingMinutes() == Torrent::NO_SEEDING_TIME_LIMIT) && !hasPerTorrentSeedingTimeLimit()
|
||||
&& (globalMaxInactiveSeedingMinutes() == Torrent::NO_INACTIVE_SEEDING_TIME_LIMIT) && !hasPerTorrentInactiveSeedingTimeLimit())
|
||||
{
|
||||
if (m_seedingLimitTimer->isActive())
|
||||
m_seedingLimitTimer->stop();
|
||||
@@ -5206,6 +5265,14 @@ bool SessionImpl::hasPerTorrentSeedingTimeLimit() const
|
||||
});
|
||||
}
|
||||
|
||||
bool SessionImpl::hasPerTorrentInactiveSeedingTimeLimit() const
|
||||
{
|
||||
return std::any_of(m_torrents.cbegin(), m_torrents.cend(), [](const TorrentImpl *torrent)
|
||||
{
|
||||
return (torrent->inactiveSeedingTimeLimit() >= 0);
|
||||
});
|
||||
}
|
||||
|
||||
void SessionImpl::configureDeferred()
|
||||
{
|
||||
if (m_deferredConfigureScheduled)
|
||||
|
||||
@@ -182,6 +182,8 @@ namespace BitTorrent
|
||||
void setGlobalMaxRatio(qreal ratio) override;
|
||||
int globalMaxSeedingMinutes() const override;
|
||||
void setGlobalMaxSeedingMinutes(int minutes) override;
|
||||
int globalMaxInactiveSeedingMinutes() const override;
|
||||
void setGlobalMaxInactiveSeedingMinutes(int minutes) override;
|
||||
bool isDHTEnabled() const override;
|
||||
void setDHTEnabled(bool enabled) override;
|
||||
bool isLSDEnabled() const override;
|
||||
@@ -513,6 +515,7 @@ namespace BitTorrent
|
||||
|
||||
bool hasPerTorrentRatioLimit() const;
|
||||
bool hasPerTorrentSeedingTimeLimit() const;
|
||||
bool hasPerTorrentInactiveSeedingTimeLimit() const;
|
||||
|
||||
// Session configuration
|
||||
Q_INVOKABLE void configure();
|
||||
@@ -660,6 +663,7 @@ namespace BitTorrent
|
||||
CachedSettingValue<QString> m_additionalTrackers;
|
||||
CachedSettingValue<qreal> m_globalMaxRatio;
|
||||
CachedSettingValue<int> m_globalMaxSeedingMinutes;
|
||||
CachedSettingValue<int> m_globalMaxInactiveSeedingMinutes;
|
||||
CachedSettingValue<bool> m_isAddTorrentToQueueTop;
|
||||
CachedSettingValue<bool> m_isAddTorrentPaused;
|
||||
CachedSettingValue<Torrent::StopCondition> m_torrentStopCondition;
|
||||
|
||||
@@ -52,8 +52,12 @@ namespace BitTorrent
|
||||
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 = 9999;
|
||||
const int Torrent::MAX_SEEDING_TIME = 525600;
|
||||
const int Torrent::MAX_INACTIVE_SEEDING_TIME = 525600;
|
||||
|
||||
TorrentID Torrent::id() const
|
||||
{
|
||||
|
||||
@@ -126,8 +126,12 @@ namespace BitTorrent
|
||||
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;
|
||||
static const int MAX_SEEDING_TIME;
|
||||
static const int MAX_INACTIVE_SEEDING_TIME;
|
||||
|
||||
using TorrentContentHandler::TorrentContentHandler;
|
||||
|
||||
@@ -210,6 +214,7 @@ namespace BitTorrent
|
||||
virtual QDateTime addedTime() const = 0;
|
||||
virtual qreal ratioLimit() const = 0;
|
||||
virtual int seedingTimeLimit() const = 0;
|
||||
virtual int inactiveSeedingTimeLimit() const = 0;
|
||||
|
||||
virtual PathList filePaths() const = 0;
|
||||
|
||||
@@ -264,6 +269,7 @@ namespace BitTorrent
|
||||
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 int uploadPayloadRate() const = 0;
|
||||
virtual int downloadPayloadRate() const = 0;
|
||||
@@ -283,6 +289,7 @@ namespace BitTorrent
|
||||
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;
|
||||
|
||||
@@ -251,6 +251,7 @@ TorrentImpl::TorrentImpl(SessionImpl *session, lt::session *nativeSession
|
||||
, m_tags(params.tags)
|
||||
, m_ratioLimit(params.ratioLimit)
|
||||
, m_seedingTimeLimit(params.seedingTimeLimit)
|
||||
, m_inactiveSeedingTimeLimit(params.inactiveSeedingTimeLimit)
|
||||
, m_operatingMode(params.operatingMode)
|
||||
, m_contentLayout(params.contentLayout)
|
||||
, m_hasFinishedStatus(params.hasFinishedStatus)
|
||||
@@ -862,6 +863,11 @@ int TorrentImpl::seedingTimeLimit() const
|
||||
return m_seedingTimeLimit;
|
||||
}
|
||||
|
||||
int TorrentImpl::inactiveSeedingTimeLimit() const
|
||||
{
|
||||
return m_inactiveSeedingTimeLimit;
|
||||
}
|
||||
|
||||
Path TorrentImpl::filePath(const int index) const
|
||||
{
|
||||
Q_ASSERT(index >= 0);
|
||||
@@ -1165,7 +1171,8 @@ qlonglong TorrentImpl::eta() const
|
||||
{
|
||||
const qreal maxRatioValue = maxRatio();
|
||||
const int maxSeedingTimeValue = maxSeedingTime();
|
||||
if ((maxRatioValue < 0) && (maxSeedingTimeValue < 0)) return MAX_ETA;
|
||||
const int maxInactiveSeedingTimeValue = maxInactiveSeedingTime();
|
||||
if ((maxRatioValue < 0) && (maxSeedingTimeValue < 0) && (maxInactiveSeedingTimeValue < 0)) return MAX_ETA;
|
||||
|
||||
qlonglong ratioEta = MAX_ETA;
|
||||
|
||||
@@ -1188,7 +1195,15 @@ qlonglong TorrentImpl::eta() const
|
||||
seedingTimeEta = 0;
|
||||
}
|
||||
|
||||
return std::min(ratioEta, seedingTimeEta);
|
||||
qlonglong inactiveSeedingTimeEta = MAX_ETA;
|
||||
|
||||
if (maxInactiveSeedingTimeValue >= 0)
|
||||
{
|
||||
inactiveSeedingTimeEta = (maxInactiveSeedingTimeValue * 60) - timeSinceActivity();
|
||||
inactiveSeedingTimeEta = std::max<qlonglong>(inactiveSeedingTimeEta, 0);
|
||||
}
|
||||
|
||||
return std::min({ratioEta, seedingTimeEta, inactiveSeedingTimeEta});
|
||||
}
|
||||
|
||||
if (!speedAverage.download) return MAX_ETA;
|
||||
@@ -1385,6 +1400,14 @@ int TorrentImpl::maxSeedingTime() const
|
||||
return m_seedingTimeLimit;
|
||||
}
|
||||
|
||||
int TorrentImpl::maxInactiveSeedingTime() const
|
||||
{
|
||||
if (m_inactiveSeedingTimeLimit == USE_GLOBAL_INACTIVE_SEEDING_TIME)
|
||||
return m_session->globalMaxInactiveSeedingMinutes();
|
||||
|
||||
return m_inactiveSeedingTimeLimit;
|
||||
}
|
||||
|
||||
qreal TorrentImpl::realRatio() const
|
||||
{
|
||||
const int64_t upload = m_nativeStatus.all_time_upload;
|
||||
@@ -2014,6 +2037,7 @@ void TorrentImpl::prepareResumeData(const lt::add_torrent_params ¶ms)
|
||||
resumeData.contentLayout = m_contentLayout;
|
||||
resumeData.ratioLimit = m_ratioLimit;
|
||||
resumeData.seedingTimeLimit = m_seedingTimeLimit;
|
||||
resumeData.inactiveSeedingTimeLimit = m_inactiveSeedingTimeLimit;
|
||||
resumeData.firstLastPiecePriority = m_hasFirstLastPiecePriority;
|
||||
resumeData.hasFinishedStatus = m_hasFinishedStatus;
|
||||
resumeData.stopped = m_isStopped;
|
||||
@@ -2406,6 +2430,21 @@ void TorrentImpl::setSeedingTimeLimit(int limit)
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentImpl::setInactiveSeedingTimeLimit(int limit)
|
||||
{
|
||||
if (limit < USE_GLOBAL_INACTIVE_SEEDING_TIME)
|
||||
limit = NO_INACTIVE_SEEDING_TIME_LIMIT;
|
||||
else if (limit > MAX_INACTIVE_SEEDING_TIME)
|
||||
limit = MAX_SEEDING_TIME;
|
||||
|
||||
if (m_inactiveSeedingTimeLimit != limit)
|
||||
{
|
||||
m_inactiveSeedingTimeLimit = limit;
|
||||
m_session->handleTorrentNeedSaveResumeData(this);
|
||||
m_session->handleTorrentShareLimitChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentImpl::setUploadLimit(const int limit)
|
||||
{
|
||||
const int cleanValue = cleanLimitValue(limit);
|
||||
|
||||
@@ -138,6 +138,7 @@ namespace BitTorrent
|
||||
QDateTime addedTime() const override;
|
||||
qreal ratioLimit() const override;
|
||||
int seedingTimeLimit() const override;
|
||||
int inactiveSeedingTimeLimit() const override;
|
||||
|
||||
Path filePath(int index) const override;
|
||||
Path actualFilePath(int index) const override;
|
||||
@@ -198,6 +199,7 @@ namespace BitTorrent
|
||||
qreal distributedCopies() const override;
|
||||
qreal maxRatio() const override;
|
||||
int maxSeedingTime() const override;
|
||||
int maxInactiveSeedingTime() const override;
|
||||
qreal realRatio() const override;
|
||||
int uploadPayloadRate() const override;
|
||||
int downloadPayloadRate() const override;
|
||||
@@ -220,6 +222,7 @@ namespace BitTorrent
|
||||
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;
|
||||
@@ -345,6 +348,7 @@ namespace BitTorrent
|
||||
TagSet m_tags;
|
||||
qreal m_ratioLimit;
|
||||
int m_seedingTimeLimit;
|
||||
int m_inactiveSeedingTimeLimit;
|
||||
TorrentOperatingMode m_operatingMode;
|
||||
TorrentContentLayout m_contentLayout;
|
||||
bool m_hasFinishedStatus;
|
||||
|
||||
Reference in New Issue
Block a user