Browse Source

Merge pull request #8598 from Piccirello/limit-share-ratio

WebUI Add Limit Share Ratio context menu option
adaptive-webui-19844
Mike Tzou 7 years ago committed by GitHub
parent
commit
a70942ed53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      src/webui/api/serialize/serialize_torrent.cpp
  2. 3
      src/webui/api/serialize/serialize_torrent.h
  3. 3
      src/webui/api/synccontroller.cpp
  4. 15
      src/webui/api/torrentscontroller.cpp
  5. 1
      src/webui/api/torrentscontroller.h
  6. 1
      src/webui/webui.qrc
  7. 1
      src/webui/www/private/index.html
  8. 6
      src/webui/www/private/scripts/dynamicTable.js
  9. 4
      src/webui/www/private/scripts/misc.js
  10. 44
      src/webui/www/private/scripts/mocha-init.js
  11. 167
      src/webui/www/private/shareratio.html
  12. 3
      src/webui/www/private/transferlist.html

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

@ -120,7 +120,10 @@ QVariantMap serialize(const BitTorrent::TorrentHandle &torrent)
ret[KEY_TORRENT_AMOUNT_UPLOADED_SESSION] = torrent.totalPayloadUpload(); ret[KEY_TORRENT_AMOUNT_UPLOADED_SESSION] = torrent.totalPayloadUpload();
ret[KEY_TORRENT_AMOUNT_LEFT] = torrent.incompletedSize(); ret[KEY_TORRENT_AMOUNT_LEFT] = torrent.incompletedSize();
ret[KEY_TORRENT_AMOUNT_COMPLETED] = torrent.completedSize(); ret[KEY_TORRENT_AMOUNT_COMPLETED] = torrent.completedSize();
ret[KEY_TORRENT_RATIO_LIMIT] = torrent.maxRatio(); ret[KEY_TORRENT_MAX_RATIO] = torrent.maxRatio();
ret[KEY_TORRENT_MAX_SEEDING_TIME] = torrent.maxSeedingTime();
ret[KEY_TORRENT_RATIO_LIMIT] = torrent.ratioLimit();
ret[KEY_TORRENT_SEEDING_TIME_LIMIT] = torrent.seedingTimeLimit();
ret[KEY_TORRENT_LAST_SEEN_COMPLETE_TIME] = torrent.lastSeenComplete().toTime_t(); ret[KEY_TORRENT_LAST_SEEN_COMPLETE_TIME] = torrent.lastSeenComplete().toTime_t();
ret[KEY_TORRENT_AUTO_TORRENT_MANAGEMENT] = torrent.isAutoTMMEnabled(); ret[KEY_TORRENT_AUTO_TORRENT_MANAGEMENT] = torrent.isAutoTMMEnabled();
ret[KEY_TORRENT_TIME_ACTIVE] = torrent.activeTime(); ret[KEY_TORRENT_TIME_ACTIVE] = torrent.activeTime();

3
src/webui/api/serialize/serialize_torrent.h

@ -69,7 +69,10 @@ const char KEY_TORRENT_AMOUNT_DOWNLOADED_SESSION[] = "downloaded_session";
const char KEY_TORRENT_AMOUNT_UPLOADED_SESSION[] = "uploaded_session"; const char KEY_TORRENT_AMOUNT_UPLOADED_SESSION[] = "uploaded_session";
const char KEY_TORRENT_AMOUNT_LEFT[] = "amount_left"; const char KEY_TORRENT_AMOUNT_LEFT[] = "amount_left";
const char KEY_TORRENT_AMOUNT_COMPLETED[] = "completed"; const char KEY_TORRENT_AMOUNT_COMPLETED[] = "completed";
const char KEY_TORRENT_MAX_RATIO[] = "max_ratio";
const char KEY_TORRENT_MAX_SEEDING_TIME[] = "max_seeding_time";
const char KEY_TORRENT_RATIO_LIMIT[] = "ratio_limit"; const char KEY_TORRENT_RATIO_LIMIT[] = "ratio_limit";
const char KEY_TORRENT_SEEDING_TIME_LIMIT[] = "seeding_time_limit";
const char KEY_TORRENT_LAST_SEEN_COMPLETE_TIME[] = "seen_complete"; const char KEY_TORRENT_LAST_SEEN_COMPLETE_TIME[] = "seen_complete";
const char KEY_TORRENT_LAST_ACTIVITY_TIME[] = "last_activity"; const char KEY_TORRENT_LAST_ACTIVITY_TIME[] = "last_activity";
const char KEY_TORRENT_TOTAL_SIZE[] = "total_size"; const char KEY_TORRENT_TOTAL_SIZE[] = "total_size";

3
src/webui/api/synccontroller.cpp

@ -351,7 +351,10 @@ namespace
// - "amount_left": Amount of data left to download // - "amount_left": Amount of data left to download
// - "save_path": Torrent save path // - "save_path": Torrent save path
// - "completed": Amount of data completed // - "completed": Amount of data completed
// - "max_ratio": Upload max share ratio
// - "max_seeding_time": Upload max seeding time
// - "ratio_limit": Upload share ratio limit // - "ratio_limit": Upload share ratio limit
// - "seeding_time_limit": Upload seeding time limit
// - "seen_complete": Indicates the time when the torrent was last seen complete/whole // - "seen_complete": Indicates the time when the torrent was last seen complete/whole
// - "last_activity": Last time when a chunk was downloaded/uploaded // - "last_activity": Last time when a chunk was downloaded/uploaded
// - "total_size": Size including unwanted data // - "total_size": Size including unwanted data

15
src/webui/api/torrentscontroller.cpp

@ -623,6 +623,21 @@ void TorrentsController::setDownloadLimitAction()
applyToTorrents(hashes, [limit](BitTorrent::TorrentHandle *torrent) { torrent->setDownloadLimit(limit); }); applyToTorrents(hashes, [limit](BitTorrent::TorrentHandle *torrent) { torrent->setDownloadLimit(limit); });
} }
void TorrentsController::setShareLimitsAction()
{
checkParams({"hashes", "ratioLimit", "seedingTimeLimit"});
const qreal ratioLimit = params()["ratioLimit"].toDouble();
const qlonglong seedingTimeLimit = params()["seedingTimeLimit"].toLongLong();
const QStringList hashes = params()["hashes"].split('|');
applyToTorrents(hashes, [ratioLimit, seedingTimeLimit](BitTorrent::TorrentHandle *torrent)
{
torrent->setRatioLimit(ratioLimit);
torrent->setSeedingTimeLimit(seedingTimeLimit);
});
}
void TorrentsController::toggleSequentialDownloadAction() void TorrentsController::toggleSequentialDownloadAction()
{ {
checkParams({"hashes"}); checkParams({"hashes"});

1
src/webui/api/torrentscontroller.h

@ -61,6 +61,7 @@ private slots:
void downloadLimitAction(); void downloadLimitAction();
void setUploadLimitAction(); void setUploadLimitAction();
void setDownloadLimitAction(); void setDownloadLimitAction();
void setShareLimitsAction();
void increasePrioAction(); void increasePrioAction();
void decreasePrioAction(); void decreasePrioAction();
void topPrioAction(); void topPrioAction();

1
src/webui/webui.qrc

@ -37,6 +37,7 @@
<file>www/private/scripts/prop-trackers.js</file> <file>www/private/scripts/prop-trackers.js</file>
<file>www/private/scripts/prop-webseeds.js</file> <file>www/private/scripts/prop-webseeds.js</file>
<file>www/private/setlocation.html</file> <file>www/private/setlocation.html</file>
<file>www/private/shareratio.html</file>
<file>www/private/statistics.html</file> <file>www/private/statistics.html</file>
<file>www/private/transferlist.html</file> <file>www/private/transferlist.html</file>
<file>www/private/upload.html</file> <file>www/private/upload.html</file>

1
src/webui/www/private/index.html

@ -122,6 +122,7 @@
</li> </li>
<li class="separator"><a href="#DownloadLimit"><img src="theme/kt-set-max-download-speed" alt="QBT_TR(Limit download rate...)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Limit download rate...)QBT_TR[CONTEXT=TransferListWidget]</a></li> <li class="separator"><a href="#DownloadLimit"><img src="theme/kt-set-max-download-speed" alt="QBT_TR(Limit download rate...)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Limit download rate...)QBT_TR[CONTEXT=TransferListWidget]</a></li>
<li><a href="#UploadLimit"><img src="theme/kt-set-max-upload-speed" alt="QBT_TR(Limit upload rate...)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Limit upload rate...)QBT_TR[CONTEXT=TransferListWidget]</a></li> <li><a href="#UploadLimit"><img src="theme/kt-set-max-upload-speed" alt="QBT_TR(Limit upload rate...)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Limit upload rate...)QBT_TR[CONTEXT=TransferListWidget]</a></li>
<li><a href="#ShareRatio"><img src="images/skin/ratio.png" alt="QBT_TR(Limit share ratio...)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Limit share ratio...)QBT_TR[CONTEXT=TransferListWidget]</a></li>
<li><a href="#SuperSeeding"><img src="theme/checked" alt="QBT_TR(Super seeding mode)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Super seeding mode)QBT_TR[CONTEXT=TransferListWidget]</a></li> <li><a href="#SuperSeeding"><img src="theme/checked" alt="QBT_TR(Super seeding mode)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Super seeding mode)QBT_TR[CONTEXT=TransferListWidget]</a></li>
<li class="separator"><a href="#SequentialDownload"><img src="theme/checked" alt="QBT_TR(Download in sequential order)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Download in sequential order)QBT_TR[CONTEXT=TransferListWidget]</a></li> <li class="separator"><a href="#SequentialDownload"><img src="theme/checked" alt="QBT_TR(Download in sequential order)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Download in sequential order)QBT_TR[CONTEXT=TransferListWidget]</a></li>
<li><a href="#FirstLastPiecePrio"><img src="theme/checked" alt="QBT_TR(Download first and last pieces first)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Download first and last pieces first)QBT_TR[CONTEXT=TransferListWidget]</a></li> <li><a href="#FirstLastPiecePrio"><img src="theme/checked" alt="QBT_TR(Download first and last pieces first)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Download first and last pieces first)QBT_TR[CONTEXT=TransferListWidget]</a></li>

6
src/webui/www/private/scripts/dynamicTable.js

@ -769,7 +769,7 @@ var TorrentsTable = new Class({
this.newColumn('time_active', '', 'QBT_TR(Time Active)QBT_TR[CONTEXT=TorrentModel]', 100, false); this.newColumn('time_active', '', 'QBT_TR(Time Active)QBT_TR[CONTEXT=TorrentModel]', 100, false);
this.newColumn('save_path', '', 'QBT_TR(Save path)QBT_TR[CONTEXT=TorrentModel]', 100, false); this.newColumn('save_path', '', 'QBT_TR(Save path)QBT_TR[CONTEXT=TorrentModel]', 100, false);
this.newColumn('completed', '', 'QBT_TR(Completed)QBT_TR[CONTEXT=TorrentModel]', 100, false); this.newColumn('completed', '', 'QBT_TR(Completed)QBT_TR[CONTEXT=TorrentModel]', 100, false);
this.newColumn('ratio_limit', '', 'QBT_TR(Ratio Limit)QBT_TR[CONTEXT=TorrentModel]', 100, false); this.newColumn('max_ratio', '', 'QBT_TR(Ratio Limit)QBT_TR[CONTEXT=TorrentModel]', 100, false);
this.newColumn('seen_complete', '', 'QBT_TR(Last Seen Complete)QBT_TR[CONTEXT=TorrentModel]', 100, false); this.newColumn('seen_complete', '', 'QBT_TR(Last Seen Complete)QBT_TR[CONTEXT=TorrentModel]', 100, false);
this.newColumn('last_activity', '', 'QBT_TR(Last Activity)QBT_TR[CONTEXT=TorrentModel]', 100, false); this.newColumn('last_activity', '', 'QBT_TR(Last Activity)QBT_TR[CONTEXT=TorrentModel]', 100, false);
@ -1076,8 +1076,8 @@ var TorrentsTable = new Class({
this.columns['save_path'].updateTd = this.columns['name'].updateTd; this.columns['save_path'].updateTd = this.columns['name'].updateTd;
this.columns['tracker'].updateTd = this.columns['name'].updateTd; this.columns['tracker'].updateTd = this.columns['name'].updateTd;
// ratio_limit // max_ratio
this.columns['ratio_limit'].updateTd = this.columns['ratio'].updateTd; this.columns['max_ratio'].updateTd = this.columns['ratio'].updateTd;
// last_activity // last_activity
this.columns['last_activity'].updateTd = function(td, row) { this.columns['last_activity'].updateTd = function(td, row) {

4
src/webui/www/private/scripts/misc.js

@ -76,6 +76,10 @@ function friendlyPercentage(value) {
return percentage.toFixed(1) + "%"; return percentage.toFixed(1) + "%";
} }
function friendlyFloat(value, precision) {
return parseFloat(value).toFixed(precision);
}
/* /*
* From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString * From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
*/ */

44
src/webui/www/private/scripts/mocha-init.js

@ -146,7 +146,6 @@ initializeWindows = function() {
uploadLimitFN = function() { uploadLimitFN = function() {
var hashes = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (hashes.length) { if (hashes.length) {
var hash = hashes[0];
new MochaUI.Window({ new MochaUI.Window({
id: 'uploadLimitPage', id: 'uploadLimitPage',
title: "QBT_TR(Torrent Upload Speed Limiting)QBT_TR[CONTEXT=TransferListWidget]", title: "QBT_TR(Torrent Upload Speed Limiting)QBT_TR[CONTEXT=TransferListWidget]",
@ -163,6 +162,45 @@ initializeWindows = function() {
} }
}; };
shareRatioFN = function() {
var hashes = torrentsTable.selectedRowsIds();
if (hashes.length) {
var shareRatio = null;
var torrentsHaveSameShareRatio = true;
// check if all selected torrents have same share ratio
for (var i = 0; i < hashes.length; i++) {
var hash = hashes[i];
var row = torrentsTable.rows[hash].full_data;
var origValues = row.ratio_limit + "|" + row.seeding_time_limit + "|" + row.max_ratio + "|" + row.max_seeding_time;
// initialize value
if (shareRatio === null)
shareRatio = origValues;
if (origValues !== shareRatio) {
torrentsHaveSameShareRatio = false;
break;
}
}
// if all torrents have same share ratio, display that share ratio. else use the default
var orig = torrentsHaveSameShareRatio ? shareRatio : "";
new MochaUI.Window({
id: 'shareRatioPage',
title: "QBT_TR(Torrent Upload/Download Ratio Limiting)QBT_TR[CONTEXT=UpDownRatioDlg]",
loadMethod: 'iframe',
contentURL: 'shareratio.html?hashes=' + hashes.join("|") + '&orig=' + orig,
scrollbars: false,
maximizable: false,
paddingVertical: 0,
paddingHorizontal: 0,
width: 424,
height: 175
});
}
};
toggleSequentialDownloadFN = function() { toggleSequentialDownloadFN = function() {
var hashes = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (hashes.length) { if (hashes.length) {
@ -257,7 +295,6 @@ initializeWindows = function() {
downloadLimitFN = function() { downloadLimitFN = function() {
var hashes = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (hashes.length) { if (hashes.length) {
var hash = hashes[0];
new MochaUI.Window({ new MochaUI.Window({
id: 'downloadLimitPage', id: 'downloadLimitPage',
title: "QBT_TR(Torrent Download Speed Limiting)QBT_TR[CONTEXT=TransferListWidget]", title: "QBT_TR(Torrent Download Speed Limiting)QBT_TR[CONTEXT=TransferListWidget]",
@ -388,12 +425,11 @@ initializeWindows = function() {
var hash = hashes[0]; var hash = hashes[0];
var row = torrentsTable.rows[hash]; var row = torrentsTable.rows[hash];
if (row) { if (row) {
var name = row.full_data.name;
new MochaUI.Window({ new MochaUI.Window({
id: 'renamePage', id: 'renamePage',
title: "QBT_TR(Rename)QBT_TR[CONTEXT=TransferListWidget]", title: "QBT_TR(Rename)QBT_TR[CONTEXT=TransferListWidget]",
loadMethod: 'iframe', loadMethod: 'iframe',
contentURL: 'rename.html?hash=' + hashes[0] + '&name=' + name, contentURL: 'rename.html?hash=' + hashes[0] + '&name=' + row.full_data.name,
scrollbars: false, scrollbars: false,
resizable: false, resizable: false,
maximizable: false, maximizable: false,

167
src/webui/www/private/shareratio.html

@ -0,0 +1,167 @@
<!DOCTYPE html>
<html lang="${LANG}">
<head>
<meta charset="UTF-8" />
<title>QBT_TR(Torrent Upload/Download Ratio Limiting)QBT_TR[CONTEXT=UpDownRatioDlg]</title>
<link rel="stylesheet" href="css/style.css" type="text/css" />
<script src="scripts/lib/mootools-1.2-core-yc.js"></script>
<script src="scripts/lib/mootools-1.2-more.js"></script>
<script src="scripts/misc.js"></script>
<script>
var UseGlobalLimit = -2;
var NoLimit = -1;
var keyboardEvents = new Keyboard({
defaultEventType: 'keydown',
events: {
'enter': function(event) {
$('save').click();
event.preventDefault();
}
}
});
keyboardEvents.activate();
window.addEvent('domready', function() {
var hashesList = new URI().getData('hashes').split('|');
var origValues = new URI().getData('orig').split('|');
var values = {
ratioLimit: friendlyFloat(origValues[0], 2),
seedingTimeLimit: parseInt(origValues[1]),
maxRatio: friendlyFloat(origValues[2], 2),
maxSeedingTime: parseInt(origValues[3])
};
// select default when orig values not passed. using double equals to compare string and int
if ((origValues[0] === "") || ((values.ratioLimit == UseGlobalLimit) && (values.seedingTimeLimit == UseGlobalLimit))) {
// use default option
setSelectedRadioValue('shareLimit', 'default');
}
else if ((values.maxRatio == NoLimit) && (values.maxSeedingTime == NoLimit)) {
setSelectedRadioValue('shareLimit', 'none');
// TODO set input boxes to *global* max ratio and seeding time
}
else {
setSelectedRadioValue('shareLimit', 'custom');
if (values.ratioLimit >= 0) {
$('setRatio').set('checked', true);
$('ratio').set('value', values.ratioLimit);
}
if (values.seedingTimeLimit >= 0) {
$('setMinutes').set('checked', true);
$('minutes').set('value', values.seedingTimeLimit);
}
}
shareLimitChanged();
$('default').focus();
$('save').addEvent('click', function(e) {
new Event(e).stop();
if (!isFormValid()) {
return false;
}
var shareLimit = getSelectedRadioValue('shareLimit');
var ratioLimitValue = 0.00;
var seedingTimeLimitValue = 0;
if (shareLimit === 'default') {
ratioLimitValue = seedingTimeLimitValue = UseGlobalLimit;
}
else if (shareLimit === 'none') {
ratioLimitValue = seedingTimeLimitValue = NoLimit;
}
else if (shareLimit === 'custom') {
ratioLimitValue = $('setRatio').get('checked') ? $('ratio').get('value') : -1;
seedingTimeLimitValue = $('setMinutes').get('checked') ? $('minutes').get('value') : -1;
}
else {
return false;
}
new Request({
url: 'api/v2/torrents/setShareLimits',
method: 'post',
data: {
hashes: hashesList.join('|'),
ratioLimit: ratioLimitValue,
seedingTimeLimit: seedingTimeLimitValue
},
onComplete: function() {
window.parent.closeWindows();
}
}).send();
});
});
function getSelectedRadioValue(name) {
var radios = document.getElementsByName(name);
for (var i = 0; i < radios.length; ++i) {
var radio = radios[i];
if (radio.checked) {
return (radio).get('value');
}
}
}
function setSelectedRadioValue(name, value) {
var radios = document.getElementsByName(name);
for (var i = 0; i < radios.length; ++i) {
var radio = radios[i];
if (radio.value === value)
radio.checked = true;
}
}
function shareLimitChanged() {
var customShareLimit = getSelectedRadioValue('shareLimit') === 'custom';
$('setRatio').set('disabled', !customShareLimit);
$('setMinutes').set('disabled', !customShareLimit);
enableInputBoxes();
$('save').set('disabled', !isFormValid());
}
function enableInputBoxes() {
$('ratio').set('disabled', ($('setRatio').get('disabled') || !$('setRatio').get('checked')));
$('minutes').set('disabled', ($('setMinutes').get('disabled') || !$('setMinutes').get('checked')));
$('save').set('disabled', !isFormValid());
}
function isFormValid() {
return !((getSelectedRadioValue('shareLimit') === 'custom') && !$('setRatio').get('checked') && !$('setMinutes').get('checked'));
}
</script>
</head>
<body>
<div style="padding: 10px 10px 0px 10px;">
<input type="radio" name="shareLimit" id="default" value="default" onchange="shareLimitChanged()" checked style="margin-bottom: 5px;" />QBT_TR(Use global share limit)QBT_TR[CONTEXT=UpDownRatioDlg]</br>
<input type="radio" name="shareLimit" value="none" onchange="shareLimitChanged()" style="margin-bottom: 5px;" />QBT_TR(Set no share limit)QBT_TR[CONTEXT=UpDownRatioDlg]</br>
<input type="radio" name="shareLimit" value="custom" onchange="shareLimitChanged()" style="margin-bottom: 5px;" />QBT_TR(Set share limit to)QBT_TR[CONTEXT=UpDownRatioDlg]</br>
<div style="margin-left: 40px; margin-bottom: 5px;">
<input type="checkbox" id="setRatio" class="shareLimitInput" onclick="enableInputBoxes()" />
<label for="setRatio" class="leftLabelLarge">QBT_TR(ratio)QBT_TR[CONTEXT=UpDownRatioDlg]</label>
<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" class="leftLabelLarge">QBT_TR(minutes)QBT_TR[CONTEXT=UpDownRatioDlg]</label>
<input type="number" id="minutes" 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" />
</div>
</div>
</body>
</html>

3
src/webui/www/private/transferlist.html

@ -61,6 +61,9 @@
UploadLimit: function(element, ref) { UploadLimit: function(element, ref) {
uploadLimitFN(); uploadLimitFN();
}, },
ShareRatio : function (element, ref) {
shareRatioFN();
},
SequentialDownload: function(element, ref) { SequentialDownload: function(element, ref) {
toggleSequentialDownloadFN(); toggleSequentialDownloadFN();

Loading…
Cancel
Save