mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2026-01-02 21:52:32 -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:
@@ -258,6 +258,8 @@ void AppController::preferencesAction()
|
||||
data[u"max_ratio"_s] = session->globalMaxRatio();
|
||||
data[u"max_seeding_time_enabled"_s] = (session->globalMaxSeedingMinutes() >= 0.);
|
||||
data[u"max_seeding_time"_s] = session->globalMaxSeedingMinutes();
|
||||
data[u"max_inactive_seeding_time_enabled"_s] = (session->globalMaxInactiveSeedingMinutes() >= 0.);
|
||||
data[u"max_inactive_seeding_time"_s] = session->globalMaxInactiveSeedingMinutes();
|
||||
data[u"max_ratio_act"_s] = session->maxRatioAction();
|
||||
// Add trackers
|
||||
data[u"add_trackers_enabled"_s] = session->isAddTrackersEnabled();
|
||||
@@ -739,6 +741,11 @@ void AppController::setPreferencesAction()
|
||||
else
|
||||
session->setGlobalMaxSeedingMinutes(-1);
|
||||
}
|
||||
if (hasKey(u"max_inactive_seeding_time_enabled"_s))
|
||||
{
|
||||
session->setGlobalMaxInactiveSeedingMinutes(it.value().toBool()
|
||||
? m[u"max_inactive_seeding_time"_s].toInt() : -1);
|
||||
}
|
||||
if (hasKey(u"max_ratio_act"_s))
|
||||
session->setMaxRatioAction(static_cast<MaxRatioAction>(it.value().toInt()));
|
||||
// Add trackers
|
||||
|
||||
@@ -148,9 +148,11 @@ QVariantMap serialize(const BitTorrent::Torrent &torrent)
|
||||
{KEY_TORRENT_AMOUNT_COMPLETED, torrent.completedSize()},
|
||||
{KEY_TORRENT_MAX_RATIO, torrent.maxRatio()},
|
||||
{KEY_TORRENT_MAX_SEEDING_TIME, torrent.maxSeedingTime()},
|
||||
{KEY_TORRENT_MAX_INACTIVE_SEEDING_TIME, torrent.maxInactiveSeedingTime()},
|
||||
{KEY_TORRENT_RATIO, adjustRatio(torrent.realRatio())},
|
||||
{KEY_TORRENT_RATIO_LIMIT, torrent.ratioLimit()},
|
||||
{KEY_TORRENT_SEEDING_TIME_LIMIT, torrent.seedingTimeLimit()},
|
||||
{KEY_TORRENT_INACTIVE_SEEDING_TIME_LIMIT, torrent.inactiveSeedingTimeLimit()},
|
||||
{KEY_TORRENT_LAST_SEEN_COMPLETE_TIME, torrent.lastSeenComplete().toSecsSinceEpoch()},
|
||||
{KEY_TORRENT_AUTO_TORRENT_MANAGEMENT, torrent.isAutoTMMEnabled()},
|
||||
{KEY_TORRENT_TIME_ACTIVE, torrent.activeTime()},
|
||||
|
||||
@@ -79,8 +79,10 @@ inline const QString KEY_TORRENT_AMOUNT_LEFT = u"amount_left"_s;
|
||||
inline const QString KEY_TORRENT_AMOUNT_COMPLETED = u"completed"_s;
|
||||
inline const QString KEY_TORRENT_MAX_RATIO = u"max_ratio"_s;
|
||||
inline const QString KEY_TORRENT_MAX_SEEDING_TIME = u"max_seeding_time"_s;
|
||||
inline const QString KEY_TORRENT_MAX_INACTIVE_SEEDING_TIME = u"max_inactive_seeding_time"_s;
|
||||
inline const QString KEY_TORRENT_RATIO_LIMIT = u"ratio_limit"_s;
|
||||
inline const QString KEY_TORRENT_SEEDING_TIME_LIMIT = u"seeding_time_limit"_s;
|
||||
inline const QString KEY_TORRENT_INACTIVE_SEEDING_TIME_LIMIT = u"inactive_seeding_time_limit"_s;
|
||||
inline const QString KEY_TORRENT_LAST_SEEN_COMPLETE_TIME = u"seen_complete"_s;
|
||||
inline const QString KEY_TORRENT_LAST_ACTIVITY_TIME = u"last_activity"_s;
|
||||
inline const QString KEY_TORRENT_TOTAL_SIZE = u"total_size"_s;
|
||||
|
||||
@@ -673,6 +673,7 @@ void TorrentsController::addAction()
|
||||
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 std::optional<bool> autoTMM = parseBool(params()[u"autoTMM"_s]);
|
||||
|
||||
const QString stopConditionParam = params()[u"stopCondition"_s];
|
||||
@@ -720,6 +721,7 @@ void TorrentsController::addAction()
|
||||
addTorrentParams.uploadLimit = upLimit;
|
||||
addTorrentParams.downloadLimit = dlLimit;
|
||||
addTorrentParams.seedingTimeLimit = seedingTimeLimit;
|
||||
addTorrentParams.inactiveSeedingTimeLimit = inactiveSeedingTimeLimit;
|
||||
addTorrentParams.ratioLimit = ratioLimit;
|
||||
addTorrentParams.useAutoTMM = autoTMM;
|
||||
|
||||
@@ -980,16 +982,18 @@ void TorrentsController::setDownloadLimitAction()
|
||||
|
||||
void TorrentsController::setShareLimitsAction()
|
||||
{
|
||||
requireParams({u"hashes"_s, u"ratioLimit"_s, u"seedingTimeLimit"_s});
|
||||
requireParams({u"hashes"_s, u"ratioLimit"_s, u"seedingTimeLimit"_s, u"inactiveSeedingTimeLimit"_s});
|
||||
|
||||
const qreal ratioLimit = params()[u"ratioLimit"_s].toDouble();
|
||||
const qlonglong seedingTimeLimit = params()[u"seedingTimeLimit"_s].toLongLong();
|
||||
const qlonglong inactiveSeedingTimeLimit = params()[u"inactiveSeedingTimeLimit"_s].toLongLong();
|
||||
const QStringList hashes = params()[u"hashes"_s].split(u'|');
|
||||
|
||||
applyToTorrents(hashes, [ratioLimit, seedingTimeLimit](BitTorrent::Torrent *const torrent)
|
||||
applyToTorrents(hashes, [ratioLimit, seedingTimeLimit, inactiveSeedingTimeLimit](BitTorrent::Torrent *const torrent)
|
||||
{
|
||||
torrent->setRatioLimit(ratioLimit);
|
||||
torrent->setSeedingTimeLimit(seedingTimeLimit);
|
||||
torrent->setInactiveSeedingTimeLimit(inactiveSeedingTimeLimit);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -240,7 +240,8 @@ const initializeWindows = function() {
|
||||
for (let i = 0; i < hashes.length; ++i) {
|
||||
const hash = hashes[i];
|
||||
const row = torrentsTable.rows[hash].full_data;
|
||||
const origValues = row.ratio_limit + "|" + row.seeding_time_limit + "|" + row.max_ratio + "|" + row.max_seeding_time;
|
||||
const origValues = row.ratio_limit + "|" + row.seeding_time_limit + "|" + row.inactive_seeding_time_limit + "|"
|
||||
+ row.max_ratio + "|" + row.max_seeding_time + "|" + row.max_inactive_seeding_time;
|
||||
|
||||
// initialize value
|
||||
if (shareRatio === null)
|
||||
|
||||
@@ -39,16 +39,19 @@
|
||||
const values = {
|
||||
ratioLimit: window.qBittorrent.Misc.friendlyFloat(origValues[0], 2),
|
||||
seedingTimeLimit: parseInt(origValues[1]),
|
||||
maxRatio: window.qBittorrent.Misc.friendlyFloat(origValues[2], 2),
|
||||
maxSeedingTime: parseInt(origValues[3])
|
||||
inactiveSeedingTimeLimit: parseInt(origValues[2]),
|
||||
maxRatio: window.qBittorrent.Misc.friendlyFloat(origValues[3], 2),
|
||||
maxSeedingTime: parseInt(origValues[4]),
|
||||
maxInactiveSeedingTime: parseInt(origValues[5])
|
||||
};
|
||||
|
||||
// select default when orig values not passed. using double equals to compare string and int
|
||||
if ((origValues[0] === "") || ((values.ratioLimit == UseGlobalLimit) && (values.seedingTimeLimit == UseGlobalLimit))) {
|
||||
if ((origValues[0] === "") || ((values.ratioLimit == UseGlobalLimit) && (values.seedingTimeLimit == UseGlobalLimit))
|
||||
&& (values.inactiveSeedingTimeLimit == UseGlobalLimit)) {
|
||||
// use default option
|
||||
setSelectedRadioValue('shareLimit', 'default');
|
||||
}
|
||||
else if ((values.maxRatio == NoLimit) && (values.maxSeedingTime == NoLimit)) {
|
||||
else if ((values.maxRatio == NoLimit) && (values.maxSeedingTime == NoLimit) && (values.maxInactiveSeedingTime == NoLimit)) {
|
||||
setSelectedRadioValue('shareLimit', 'none');
|
||||
// TODO set input boxes to *global* max ratio and seeding time
|
||||
}
|
||||
@@ -59,8 +62,12 @@
|
||||
$('ratio').set('value', values.ratioLimit);
|
||||
}
|
||||
if (values.seedingTimeLimit >= 0) {
|
||||
$('setMinutes').set('checked', true);
|
||||
$('minutes').set('value', values.seedingTimeLimit);
|
||||
$('setTotalMinutes').set('checked', true);
|
||||
$('totalMinutes').set('value', values.seedingTimeLimit);
|
||||
}
|
||||
if (values.inactiveSeedingTimeLimit >= 0) {
|
||||
$('setInactiveMinutes').set('checked', true);
|
||||
$('inactiveMinutes').set('value', values.inactiveSeedingTimeLimit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,16 +84,18 @@
|
||||
const shareLimit = getSelectedRadioValue('shareLimit');
|
||||
let ratioLimitValue = 0.00;
|
||||
let seedingTimeLimitValue = 0;
|
||||
let inactiveSeedingTimeLimitValue = 0;
|
||||
|
||||
if (shareLimit === 'default') {
|
||||
ratioLimitValue = seedingTimeLimitValue = UseGlobalLimit;
|
||||
ratioLimitValue = seedingTimeLimitValue = inactiveSeedingTimeLimitValue = UseGlobalLimit;
|
||||
}
|
||||
else if (shareLimit === 'none') {
|
||||
ratioLimitValue = seedingTimeLimitValue = NoLimit;
|
||||
ratioLimitValue = seedingTimeLimitValue = inactiveSeedingTimeLimitValue = NoLimit;
|
||||
}
|
||||
else if (shareLimit === 'custom') {
|
||||
ratioLimitValue = $('setRatio').get('checked') ? $('ratio').get('value') : -1;
|
||||
seedingTimeLimitValue = $('setMinutes').get('checked') ? $('minutes').get('value') : -1;
|
||||
seedingTimeLimitValue = $('setTotalMinutes').get('checked') ? $('totalMinutes').get('value') : -1;
|
||||
inactiveSeedingTimeLimitValue = $('setInactiveMinutes').get('checked') ? $('inactiveMinutes').get('value') : -1;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
@@ -98,7 +107,8 @@
|
||||
data: {
|
||||
hashes: hashesList.join('|'),
|
||||
ratioLimit: ratioLimitValue,
|
||||
seedingTimeLimit: seedingTimeLimitValue
|
||||
seedingTimeLimit: seedingTimeLimitValue,
|
||||
inactiveSeedingTimeLimit: inactiveSeedingTimeLimitValue
|
||||
},
|
||||
onComplete: function() {
|
||||
window.parent.closeWindows();
|
||||
@@ -131,7 +141,8 @@
|
||||
function shareLimitChanged() {
|
||||
const customShareLimit = getSelectedRadioValue('shareLimit') === 'custom';
|
||||
$('setRatio').set('disabled', !customShareLimit);
|
||||
$('setMinutes').set('disabled', !customShareLimit);
|
||||
$('setTotalMinutes').set('disabled', !customShareLimit);
|
||||
$('setInactiveMinutes').set('disabled', !customShareLimit);
|
||||
|
||||
enableInputBoxes();
|
||||
|
||||
@@ -140,13 +151,15 @@
|
||||
|
||||
function enableInputBoxes() {
|
||||
$('ratio').set('disabled', ($('setRatio').get('disabled') || !$('setRatio').get('checked')));
|
||||
$('minutes').set('disabled', ($('setMinutes').get('disabled') || !$('setMinutes').get('checked')));
|
||||
$('totalMinutes').set('disabled', ($('setTotalMinutes').get('disabled') || !$('setTotalMinutes').get('checked')));
|
||||
$('inactiveMinutes').set('disabled', ($('setInactiveMinutes').get('disabled') || !$('setInactiveMinutes').get('checked')));
|
||||
|
||||
$('save').set('disabled', !isFormValid());
|
||||
}
|
||||
|
||||
function isFormValid() {
|
||||
return !((getSelectedRadioValue('shareLimit') === 'custom') && !$('setRatio').get('checked') && !$('setMinutes').get('checked'));
|
||||
return !((getSelectedRadioValue('shareLimit') === 'custom') && !$('setRatio').get('checked')
|
||||
&& !$('setTotalMinutes').get('checked') && !$('setInactiveMinutes').get('checked'));
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
@@ -163,9 +176,14 @@
|
||||
<input type="number" id="ratio" value="0.00" step=".01" min="0" max="9999" class="shareLimitInput" />
|
||||
</div>
|
||||
<div style="margin-left: 40px; margin-bottom: 5px;">
|
||||
<input type="checkbox" id="setMinutes" class="shareLimitInput" onclick="enableInputBoxes()" />
|
||||
<label for="setMinutes">QBT_TR(minutes)QBT_TR[CONTEXT=UpDownRatioDialog]</label>
|
||||
<input type="number" id="minutes" value="0" step="1" min="0" max="525600" class="shareLimitInput" />
|
||||
<input type="checkbox" id="setTotalMinutes" class="shareLimitInput" onclick="enableInputBoxes()" />
|
||||
<label for="setTotalMinutes">QBT_TR(total minutes)QBT_TR[CONTEXT=UpDownRatioDialog]</label>
|
||||
<input type="number" id="totalMinutes" value="0" step="1" min="0" max="525600" class="shareLimitInput" />
|
||||
</div>
|
||||
<div style="margin-left: 40px; margin-bottom: 5px;">
|
||||
<input type="checkbox" id="setInactiveMinutes" class="shareLimitInput" onclick="enableInputBoxes()" />
|
||||
<label for="setInactiveMinutes">QBT_TR(inactive minutes)QBT_TR[CONTEXT=UpDownRatioDialog]</label>
|
||||
<input type="number" id="inactiveMinutes" value="0" step="1" min="0" max="525600" class="shareLimitInput" />
|
||||
</div>
|
||||
<div style="text-align: center; padding-top: 10px;">
|
||||
<input type="button" value="QBT_TR(Save)QBT_TR[CONTEXT=HttpServer]" id="save" />
|
||||
|
||||
@@ -650,12 +650,21 @@
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" id="max_seeding_time_checkbox" onclick="qBittorrent.Preferences.updateMaxRatioTimeEnabled();" />
|
||||
<label for="max_seeding_time_checkbox">QBT_TR(When seeding time reaches)QBT_TR[CONTEXT=OptionsDialog]</label>
|
||||
<label for="max_seeding_time_checkbox">QBT_TR(When total seeding time reaches)QBT_TR[CONTEXT=OptionsDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="max_seeding_time_value" style="width: 4em;" />QBT_TR(minutes)QBT_TR[CONTEXT=OptionsDialog]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" id="max_inactive_seeding_time_checkbox" onclick="qBittorrent.Preferences.updateMaxRatioTimeEnabled();" />
|
||||
<label for="max_inactive_seeding_time_checkbox">QBT_TR(When inactive seeding time reaches)QBT_TR[CONTEXT=OptionsDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="max_inactive_seeding_time_value" style="width: 4em;" />QBT_TR(minutes)QBT_TR[CONTEXT=OptionsDialog]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: right;"><label for="max_ratio_act">QBT_TR(then)QBT_TR[CONTEXT=OptionsDialog]</label></td>
|
||||
<td>
|
||||
@@ -1700,7 +1709,10 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||
const isMaxSeedingTimeEnabled = $('max_seeding_time_checkbox').getProperty('checked');
|
||||
$('max_seeding_time_value').setProperty('disabled', !isMaxSeedingTimeEnabled);
|
||||
|
||||
$('max_ratio_act').setProperty('disabled', !(isMaxRatioEnabled || isMaxSeedingTimeEnabled));
|
||||
const isMaxInactiveSeedingTimeEnabled = $('max_inactive_seeding_time_checkbox').getProperty('checked');
|
||||
$('max_inactive_seeding_time_value').setProperty('disabled', !isMaxInactiveSeedingTimeEnabled);
|
||||
|
||||
$('max_ratio_act').setProperty('disabled', !(isMaxRatioEnabled || isMaxSeedingTimeEnabled || isMaxInactiveSeedingTimeEnabled));
|
||||
};
|
||||
|
||||
const updateAddTrackersEnabled = function() {
|
||||
@@ -2081,6 +2093,8 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||
$('max_ratio_value').setProperty('value', (pref.max_ratio_enabled ? pref.max_ratio : 1));
|
||||
$('max_seeding_time_checkbox').setProperty('checked', pref.max_seeding_time_enabled);
|
||||
$('max_seeding_time_value').setProperty('value', (pref.max_seeding_time_enabled ? pref.max_seeding_time.toInt() : 1440));
|
||||
$('max_inactive_seeding_time_checkbox').setProperty('checked', pref.max_inactive_seeding_time_enabled);
|
||||
$('max_inactive_seeding_time_value').setProperty('value', (pref.max_inactive_seeding_time_enabled ? pref.max_inactive_seeding_time.toInt() : 1440));
|
||||
let maxRatioAct = 0;
|
||||
switch (pref.max_ratio_act.toInt()) {
|
||||
case 0: // Pause
|
||||
@@ -2488,6 +2502,18 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||
settings.set('max_seeding_time', max_seeding_time);
|
||||
settings.set('max_ratio_act', $('max_ratio_act').getProperty('value').toInt());
|
||||
|
||||
let max_inactive_seeding_time = -1;
|
||||
if ($('max_inactive_seeding_time_checkbox').getProperty('checked')) {
|
||||
max_inactive_seeding_time = $('max_inactive_seeding_time_value').getProperty('value').toInt();
|
||||
if (isNaN(max_inactive_seeding_time) || (max_inactive_seeding_time < 0) || (max_inactive_seeding_time > 525600)) {
|
||||
alert("QBT_TR(Seeding time limit must be between 0 and 525600 minutes.)QBT_TR[CONTEXT=HttpServer]");
|
||||
return;
|
||||
}
|
||||
}
|
||||
settings.set('max_inactive_seeding_time_enabled', $('max_inactive_seeding_time_checkbox').getProperty('checked'));
|
||||
settings.set('max_inactive_seeding_time', max_inactive_seeding_time);
|
||||
settings.set('max_ratio_act', $('max_ratio_act').getProperty('value').toInt());
|
||||
|
||||
// Add trackers
|
||||
settings.set('add_trackers_enabled', $('add_trackers_checkbox').getProperty('checked'));
|
||||
settings.set('add_trackers', $('add_trackers_textarea').getProperty('value'));
|
||||
|
||||
Reference in New Issue
Block a user