Browse Source

Set priority for multiple files in one WebAPI request

Closes #6259.
adaptive-webui-19844
Thomas Piccirello 6 years ago
parent
commit
c5b8f62780
  1. 10
      src/base/bittorrent/torrenthandle.cpp
  2. 1
      src/base/bittorrent/torrenthandle.h
  3. 37
      src/webui/api/torrentscontroller.cpp
  4. 77
      src/webui/www/private/scripts/prop-files.js

10
src/base/bittorrent/torrenthandle.cpp

@ -1424,16 +1424,6 @@ bool TorrentHandle::saveTorrentFile(const QString &path)
return false; return false;
} }
void TorrentHandle::setFilePriority(int index, int priority)
{
std::vector<int> priorities = m_nativeHandle.file_priorities();
if ((priorities.size() > static_cast<quint64>(index)) && (priorities[index] != priority)) {
priorities[index] = priority;
prioritizeFiles(QVector<int>::fromStdVector(priorities));
}
}
void TorrentHandle::handleStateUpdate(const libt::torrent_status &nativeStatus) void TorrentHandle::handleStateUpdate(const libt::torrent_status &nativeStatus)
{ {
updateStatus(nativeStatus); updateStatus(nativeStatus);

1
src/base/bittorrent/torrenthandle.h

@ -348,7 +348,6 @@ namespace BitTorrent
void renameFile(int index, const QString &name); void renameFile(int index, const QString &name);
bool saveTorrentFile(const QString &path); bool saveTorrentFile(const QString &path);
void prioritizeFiles(const QVector<int> &priorities); void prioritizeFiles(const QVector<int> &priorities);
void setFilePriority(int index, int priority);
void setRatioLimit(qreal limit); void setRatioLimit(qreal limit);
void setSeedingTimeLimit(int limit); void setSeedingTimeLimit(int limit);
void setUploadLimit(int limit); void setUploadLimit(int limit);

37
src/webui/api/torrentscontroller.cpp

@ -39,6 +39,7 @@
#include <QRegularExpression> #include <QRegularExpression>
#include <QUrl> #include <QUrl>
#include "base/bittorrent/filepriority.h"
#include "base/bittorrent/session.h" #include "base/bittorrent/session.h"
#include "base/bittorrent/torrenthandle.h" #include "base/bittorrent/torrenthandle.h"
#include "base/bittorrent/torrentinfo.h" #include "base/bittorrent/torrentinfo.h"
@ -371,7 +372,7 @@ void TorrentsController::filesAction()
const QString hash {params()["hash"]}; const QString hash {params()["hash"]};
QVariantList fileList; QVariantList fileList;
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash); const BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (!torrent) if (!torrent)
throw APIError(APIErrorType::NotFound); throw APIError(APIErrorType::NotFound);
@ -561,12 +562,38 @@ void TorrentsController::filePrioAction()
checkParams({"hash", "id", "priority"}); checkParams({"hash", "id", "priority"});
const QString hash = params()["hash"]; const QString hash = params()["hash"];
int fileID = params()["id"].toInt(); bool ok = false;
int priority = params()["priority"].toInt(); const int priority = params()["priority"].toInt(&ok);
if (!ok)
throw APIError(APIErrorType::BadParams, tr("Priority must be an integer"));
if (!BitTorrent::isValidFilePriority(static_cast<BitTorrent::FilePriority>(priority)))
throw APIError(APIErrorType::BadParams, tr("Priority is not valid"));
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash); BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (!torrent)
throw APIError(APIErrorType::NotFound);
if (!torrent->hasMetadata())
throw APIError(APIErrorType::Conflict, tr("Torrent's metadata has not yet downloaded"));
const int filesCount = torrent->filesCount();
QVector<int> priorities = torrent->filePriorities();
bool priorityChanged = false;
for (const QString &fileID : params()["id"].split('|')) {
const int id = fileID.toInt(&ok);
if (!ok)
throw APIError(APIErrorType::BadParams, tr("File IDs must be integers"));
if ((id < 0) || (id >= filesCount))
throw APIError(APIErrorType::Conflict, tr("File ID is not valid"));
if (priorities[id] != priority) {
priorities[id] = priority;
priorityChanged = true;
}
}
if (torrent && torrent->hasMetadata()) if (priorityChanged)
torrent->setFilePriority(fileID, priority); torrent->prioritizeFiles(priorities);
} }
void TorrentsController::uploadLimitAction() void TorrentsController::uploadLimitAction()

77
src/webui/www/private/scripts/prop-files.js

@ -47,28 +47,34 @@ var switchCBState = function() {
if ($("all_files_cb").hasClass("partial")) { if ($("all_files_cb").hasClass("partial")) {
$("all_files_cb").removeClass("partial"); $("all_files_cb").removeClass("partial");
// Uncheck all checkboxes // Uncheck all checkboxes
var indexes = [];
$$('input.DownloadedCB').each(function(item, index) { $$('input.DownloadedCB').each(function(item, index) {
item.erase("checked"); item.erase("checked");
setFilePriority(index, 0); indexes.push(index);
}); });
setFilePriority(indexes, 0);
return; return;
} }
if ($("all_files_cb").hasClass("checked")) { if ($("all_files_cb").hasClass("checked")) {
$("all_files_cb").removeClass("checked"); $("all_files_cb").removeClass("checked");
// Uncheck all checkboxes // Uncheck all checkboxes
var indexes = [];
$$('input.DownloadedCB').each(function(item, index) { $$('input.DownloadedCB').each(function(item, index) {
item.erase("checked"); item.erase("checked");
setFilePriority(index, 0); indexes.push(index);
}); });
setFilePriority(indexes, 0);
return; return;
} }
// Check // Check
$("all_files_cb").addClass("checked"); $("all_files_cb").addClass("checked");
// Check all checkboxes // Check all checkboxes
var indexes = [];
$$('input.DownloadedCB').each(function(item, index) { $$('input.DownloadedCB').each(function(item, index) {
item.set("checked", "checked"); item.set("checked", "checked");
setFilePriority(index, 1); indexes.push(index);
}); });
setFilePriority(indexes, 1);
}; };
var allCBChecked = function() { var allCBChecked = function() {
@ -93,22 +99,31 @@ var allCBUnchecked = function() {
var setFilePriority = function(id, priority) { var setFilePriority = function(id, priority) {
if (current_hash === "") return; if (current_hash === "") return;
var ids = Array.isArray(id) ? id : [id];
new Request({ new Request({
url: 'api/v2/torrents/filePrio', url: 'api/v2/torrents/filePrio',
method: 'post', method: 'post',
data: { data: {
'hash': current_hash, 'hash': current_hash,
'id': id, 'id': ids.join('|'),
'priority': priority 'priority': priority
} }
}).send(); }).send();
// Display or add combobox // Display or add combobox
if (priority > 0) { if (priority > 0) {
$('comboPrio' + id).set("value", 1); ids.forEach(function(_id) {
$('comboPrio' + id).removeClass("invisible"); if ($('comboPrio' + _id).hasClass("invisible")) {
$('comboPrio' + _id).set("value", priority);
$('comboPrio' + _id).removeClass("invisible");
}
});
} }
else { else {
$('comboPrio' + id).addClass("invisible"); ids.forEach(function(_id) {
if (!$('comboPrio' + _id).hasClass("invisible"))
$('comboPrio' + _id).addClass("invisible");
});
} }
}; };
@ -146,24 +161,27 @@ var createPriorityCombo = function(id, selected_prio) {
var new_prio = $('comboPrio' + id).get('value'); var new_prio = $('comboPrio' + id).get('value');
setFilePriority(id, new_prio); setFilePriority(id, new_prio);
}); });
var opt = new Element("option");
opt.set('value', '1'); function createOptionElement(priority, html) {
opt.set('html', "QBT_TR(Normal)QBT_TR[CONTEXT=PropListDelegate]"); var elem = new Element("option");
if (selected_prio <= 1) elem.set('value', priority.toString());
opt.setAttribute('selected', ''); elem.set('html', html);
opt.injectInside(select); if (selected_prio == priority)
opt = new Element("option"); elem.setAttribute('selected', 'true');
opt.set('value', '2'); return elem;
opt.set('html', "QBT_TR(High)QBT_TR[CONTEXT=PropListDelegate]"); }
if (selected_prio == 2)
opt.setAttribute('selected', ''); var normal = createOptionElement(1, "QBT_TR(Normal)QBT_TR[CONTEXT=PropListDelegate]");
opt.injectInside(select); if (selected_prio <= 0)
opt = new Element("option"); normal.setAttribute('selected', '');
opt.set('value', '7'); normal.injectInside(select);
opt.set('html', "QBT_TR(Maximum)QBT_TR[CONTEXT=PropListDelegate]");
if (selected_prio == 7) var high = createOptionElement(2, "QBT_TR(High)QBT_TR[CONTEXT=PropListDelegate]");
opt.setAttribute('selected', ''); high.injectInside(select);
opt.injectInside(select);
var maximum = createOptionElement(7, "QBT_TR(Maximum)QBT_TR[CONTEXT=PropListDelegate]");
maximum.injectInside(select);
if (is_seed || selected_prio < 1) { if (is_seed || selected_prio < 1) {
select.addClass("invisible"); select.addClass("invisible");
} }
@ -203,19 +221,20 @@ var filesDynTable = new Class({
var tds = tr.getElements('td'); var tds = tr.getElements('td');
for (var i = 0; i < row.length; ++i) { for (var i = 0; i < row.length; ++i) {
switch (i) { switch (i) {
case 0: case 0: // checkbox
if (row[i] > 0) if (row[i] > 0)
tds[i].getChildren('input')[0].set('checked', 'checked'); tds[i].getChildren('input')[0].set('checked', 'checked');
else else
tds[i].getChildren('input')[0].removeProperty('checked'); tds[i].getChildren('input')[0].removeProperty('checked');
break; break;
case 3: case 3: // progress bar
$('pbf_' + id).setValue(row[i].toFloat()); $('pbf_' + id).setValue(row[i].toFloat());
break; break;
case 4: case 4: // download priority
if (!is_seed && row[i] > 0) { if (!is_seed && row[i] > 0) {
tds[i].getChildren('select').set('value', row[i]); tds[i].getChildren('select').set('value', row[i]);
$('comboPrio' + id).removeClass("invisible"); if ($('comboPrio' + id).hasClass("invisible"))
$('comboPrio' + id).removeClass("invisible");
} }
else { else {
if (!$('comboPrio' + id).hasClass("invisible")) if (!$('comboPrio' + id).hasClass("invisible"))

Loading…
Cancel
Save