Browse Source

Set torrent location from webui context menu (addresses #6815) (#7062)

* Add option to set torrent location from webui context menu (addresses #6815)

* Update debug messages

* Use logger

* Remove redundant curly braces

* Remove message

* Use log message from transferlistwidget

* Use QDir

* Remove unused import

* Check if newLocation is an empty string
adaptive-webui-19844
Tom Piccirello 7 years ago committed by Mike Tzou
parent
commit
07a85a1018
  1. 26
      src/webui/webapplication.cpp
  2. 1
      src/webui/webapplication.h
  3. 1
      src/webui/webui.qrc
  4. 3
      src/webui/www/private/index.html
  5. 2
      src/webui/www/public/newcategory.html
  6. 127
      src/webui/www/public/scripts/mocha-init.js
  7. 55
      src/webui/www/public/setlocation.html
  8. 26
      src/webui/www/public/transferlist.html

26
src/webui/webapplication.cpp

@ -34,6 +34,7 @@
#include <vector> #include <vector>
#include "base/iconprovider.h" #include "base/iconprovider.h"
#include "base/logger.h"
#include "base/utils/misc.h" #include "base/utils/misc.h"
#include "base/utils/fs.h" #include "base/utils/fs.h"
#include "base/utils/string.h" #include "base/utils/string.h"
@ -117,6 +118,7 @@ QMap<QString, QMap<QString, WebApplication::Action> > WebApplication::initialize
ADD_ACTION(command, decreasePrio); ADD_ACTION(command, decreasePrio);
ADD_ACTION(command, topPrio); ADD_ACTION(command, topPrio);
ADD_ACTION(command, bottomPrio); ADD_ACTION(command, bottomPrio);
ADD_ACTION(command, setLocation);
ADD_ACTION(command, recheck); ADD_ACTION(command, recheck);
ADD_ACTION(command, setCategory); ADD_ACTION(command, setCategory);
ADD_ACTION(command, addCategory); ADD_ACTION(command, addCategory);
@ -774,6 +776,30 @@ void WebApplication::action_command_bottomPrio()
BitTorrent::Session::instance()->bottomTorrentsPriority(hashes); BitTorrent::Session::instance()->bottomTorrentsPriority(hashes);
} }
void WebApplication::action_command_setLocation()
{
CHECK_URI(0);
CHECK_PARAMETERS("hashes" << "location");
QStringList hashes = request().posts["hashes"].split("|");
QString newLocation = request().posts["location"].trimmed();
// check location exists
if (newLocation.isEmpty() || !QDir(newLocation).exists())
return;
foreach (const QString &hash, hashes) {
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (torrent) {
// get old location
const QString oldLocation = torrent->savePath();
Logger::instance()->addMessage(tr("WebUI Set location: moving \"%1\", from \"%2\" to \"%3\"").arg(torrent->name()).arg(torrent->savePath()).arg(newLocation));
torrent->move(Utils::Fs::expandPathAbs(newLocation));
}
}
}
void WebApplication::action_command_recheck() void WebApplication::action_command_recheck()
{ {
CHECK_URI(0); CHECK_URI(0);

1
src/webui/webapplication.h

@ -90,6 +90,7 @@ private:
void action_command_decreasePrio(); void action_command_decreasePrio();
void action_command_topPrio(); void action_command_topPrio();
void action_command_bottomPrio(); void action_command_bottomPrio();
void action_command_setLocation();
void action_command_recheck(); void action_command_recheck();
void action_command_setCategory(); void action_command_setCategory();
void action_command_addCategory(); void action_command_addCategory();

1
src/webui/webui.qrc

@ -41,5 +41,6 @@
<file>www/public/upload.html</file> <file>www/public/upload.html</file>
<file>www/public/uploadlimit.html</file> <file>www/public/uploadlimit.html</file>
<file>www/public/newcategory.html</file> <file>www/public/newcategory.html</file>
<file>www/public/setlocation.html</file>
</qresource> </qresource>
</RCC> </RCC>

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

@ -108,6 +108,9 @@
<li><a href="#ForceStart"><img src="theme/media-seek-forward" alt="QBT_TR(Force Resume)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Force Resume)QBT_TR[CONTEXT=TransferListWidget]</a></li> <li><a href="#ForceStart"><img src="theme/media-seek-forward" alt="QBT_TR(Force Resume)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Force Resume)QBT_TR[CONTEXT=TransferListWidget]</a></li>
<li class="separator"><a href="#Delete"><img src="theme/list-remove" alt="QBT_TR(Delete)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Delete)QBT_TR[CONTEXT=TransferListWidget]</a></li> <li class="separator"><a href="#Delete"><img src="theme/list-remove" alt="QBT_TR(Delete)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Delete)QBT_TR[CONTEXT=TransferListWidget]</a></li>
<li class="separator"> <li class="separator">
<a href="#SetLocation"><img src="theme/inode-directory" alt="QBT_TR(Set location...)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Set location...)QBT_TR[CONTEXT=TransferListWidget]</a>
</li>
<li>
<a href="#Category" class="arrow-right"><img src="theme/view-categories" alt="QBT_TR(Category)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Category)QBT_TR[CONTEXT=TransferListWidget]</a> <a href="#Category" class="arrow-right"><img src="theme/view-categories" alt="QBT_TR(Category)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Category)QBT_TR[CONTEXT=TransferListWidget]</a>
<ul id="contextCategoryList" class="scrollableMenu"></ul> <ul id="contextCategoryList" class="scrollableMenu"></ul>
</li> </li>

2
src/webui/www/public/newcategory.html

@ -65,7 +65,7 @@
<div style="padding: 10px 10px 0px 10px;"> <div style="padding: 10px 10px 0px 10px;">
<p style="font-weight: bold;">QBT_TR(Category)QBT_TR[CONTEXT=TransferListWidget]:</p> <p style="font-weight: bold;">QBT_TR(Category)QBT_TR[CONTEXT=TransferListWidget]:</p>
<input type="text" id="newCategory" value="" maxlength="100" style="width: 220px;"/> <input type="text" id="newCategory" value="" maxlength="100" style="width: 220px;"/>
<div style="text-align: center;"> <div style="text-align: center; padding-top: 10px;">
<input type="button" value="QBT_TR(Add)QBT_TR[CONTEXT=HttpServer]" id="newCategoryButton"/> <input type="button" value="QBT_TR(Add)QBT_TR[CONTEXT=HttpServer]" id="newCategoryButton"/>
</div> </div>
</div> </div>

127
src/webui/www/public/scripts/mocha-init.js

@ -119,14 +119,14 @@ initializeWindows = function() {
}; };
uploadLimitFN = function() { uploadLimitFN = function() {
var h = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (h.length) { if (hashes.length) {
var hash = h[0]; 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]",
loadMethod: 'iframe', loadMethod: 'iframe',
contentURL: 'uploadlimit.html?hashes=' + h.join("|"), contentURL: 'uploadlimit.html?hashes=' + hashes.join("|"),
scrollbars: false, scrollbars: false,
resizable: false, resizable: false,
maximizable: false, maximizable: false,
@ -139,13 +139,13 @@ initializeWindows = function() {
}; };
toggleSequentialDownloadFN = function() { toggleSequentialDownloadFN = function() {
var h = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (h.length) { if (hashes.length) {
new Request({ new Request({
url: 'command/toggleSequentialDownload', url: 'command/toggleSequentialDownload',
method: 'post', method: 'post',
data: { data: {
hashes: h.join("|") hashes: hashes.join("|")
} }
}).send(); }).send();
updateMainData(); updateMainData();
@ -153,13 +153,13 @@ initializeWindows = function() {
}; };
toggleFirstLastPiecePrioFN = function() { toggleFirstLastPiecePrioFN = function() {
var h = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (h.length) { if (hashes.length) {
new Request({ new Request({
url: 'command/toggleFirstLastPiecePrio', url: 'command/toggleFirstLastPiecePrio',
method: 'post', method: 'post',
data: { data: {
hashes: h.join("|") hashes: hashes.join("|")
} }
}).send(); }).send();
updateMainData(); updateMainData();
@ -167,14 +167,14 @@ initializeWindows = function() {
}; };
setSuperSeedingFN = function(val) { setSuperSeedingFN = function(val) {
var h = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (h.length) { if (hashes.length) {
new Request({ new Request({
url: 'command/setSuperSeeding', url: 'command/setSuperSeeding',
method: 'post', method: 'post',
data: { data: {
value: val, value: val,
hashes: h.join("|") hashes: hashes.join("|")
} }
}).send(); }).send();
updateMainData(); updateMainData();
@ -182,14 +182,14 @@ initializeWindows = function() {
}; };
setForceStartFN = function() { setForceStartFN = function() {
var h = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (h.length) { if (hashes.length) {
new Request({ new Request({
url: 'command/setForceStart', url: 'command/setForceStart',
method: 'post', method: 'post',
data: { data: {
value: 'true', value: 'true',
hashes: h.join("|") hashes: hashes.join("|")
} }
}).send(); }).send();
updateMainData(); updateMainData();
@ -228,14 +228,14 @@ initializeWindows = function() {
}; };
downloadLimitFN = function() { downloadLimitFN = function() {
var h = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (h.length) { if (hashes.length) {
var hash = h[0]; 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]",
loadMethod: 'iframe', loadMethod: 'iframe',
contentURL: 'downloadlimit.html?hashes=' + h.join("|"), contentURL: 'downloadlimit.html?hashes=' + hashes.join("|"),
scrollbars: false, scrollbars: false,
resizable: false, resizable: false,
maximizable: false, maximizable: false,
@ -248,13 +248,13 @@ initializeWindows = function() {
}; };
deleteFN = function() { deleteFN = function() {
var h = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (h.length) { if (hashes.length) {
new MochaUI.Window({ new MochaUI.Window({
id: 'confirmDeletionPage', id: 'confirmDeletionPage',
title: "QBT_TR(Deletion confirmation)QBT_TR[CONTEXT=confirmDeletionDlg]", title: "QBT_TR(Deletion confirmation)QBT_TR[CONTEXT=confirmDeletionDlg]",
loadMethod: 'iframe', loadMethod: 'iframe',
contentURL: 'confirmdeletion.html?hashes=' + h.join("|"), contentURL: 'confirmdeletion.html?hashes=' + hashes.join("|"),
scrollbars: false, scrollbars: false,
resizable: false, resizable: false,
maximizable: false, maximizable: false,
@ -272,9 +272,9 @@ initializeWindows = function() {
}); });
pauseFN = function() { pauseFN = function() {
var h = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (h.length) { if (hashes.length) {
h.each(function(hash, index) { hashes.each(function(hash, index) {
new Request({ new Request({
url: 'command/pause', url: 'command/pause',
method: 'post', method: 'post',
@ -288,9 +288,9 @@ initializeWindows = function() {
}; };
startFN = function() { startFN = function() {
var h = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (h.length) { if (hashes.length) {
h.each(function(hash, index) { hashes.each(function(hash, index) {
new Request({ new Request({
url: 'command/resume', url: 'command/resume',
method: 'post', method: 'post',
@ -304,9 +304,9 @@ initializeWindows = function() {
}; };
recheckFN = function() { recheckFN = function() {
var h = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (h.length) { if (hashes.length) {
h.each(function(hash, index) { hashes.each(function(hash, index) {
new Request({ new Request({
url: 'command/recheck', url: 'command/recheck',
method: 'post', method: 'post',
@ -319,14 +319,33 @@ initializeWindows = function() {
} }
}; };
setLocationFN = function() {
var hashes = torrentsTable.selectedRowsIds();
if (hashes.length) {
new MochaUI.Window({
id: 'setLocationPage',
title: "QBT_TR(Set location)QBT_TR[CONTEXT=TransferListWidget]",
loadMethod: 'iframe',
contentURL: 'setlocation.html?hashes=' + hashes.join('|'),
scrollbars: false,
resizable: false,
maximizable: false,
paddingVertical: 0,
paddingHorizontal: 0,
width: 250,
height: 100
});
}
};
torrentNewCategoryFN = function () { torrentNewCategoryFN = function () {
var h = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (h.length) { if (hashes.length) {
new MochaUI.Window({ new MochaUI.Window({
id: 'newCategoryPage', id: 'newCategoryPage',
title: "QBT_TR(New Category)QBT_TR[CONTEXT=TransferListWidget]", title: "QBT_TR(New Category)QBT_TR[CONTEXT=TransferListWidget]",
loadMethod: 'iframe', loadMethod: 'iframe',
contentURL: 'newcategory.html?hashes=' + h.join('|'), contentURL: 'newcategory.html?hashes=' + hashes.join('|'),
scrollbars: false, scrollbars: false,
resizable: false, resizable: false,
maximizable: false, maximizable: false,
@ -340,15 +359,15 @@ initializeWindows = function() {
torrentSetCategoryFN = function (categoryHash) { torrentSetCategoryFN = function (categoryHash) {
var categoryName = ''; var categoryName = '';
if (categoryHash !== 0) if (categoryHash != 0)
categoryName = category_list[categoryHash].name; categoryName = category_list[categoryHash].name;
var h = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (h.length) { if (hashes.length) {
new Request({ new Request({
url: 'command/setCategory', url: 'command/setCategory',
method: 'post', method: 'post',
data: { data: {
hashes: h.join("|"), hashes: hashes.join("|"),
category: categoryName category: categoryName
} }
}).send(); }).send();
@ -401,9 +420,9 @@ initializeWindows = function() {
}; };
startTorrentsByCategoryFN = function (categoryHash) { startTorrentsByCategoryFN = function (categoryHash) {
var h = torrentsTable.getFilteredTorrentsHashes('all', categoryHash); var hashes = torrentsTable.getFilteredTorrentsHashes('all', categoryHash);
if (h.length) { if (hashes.length) {
h.each(function (hash, index) { hashes.each(function (hash, index) {
new Request({ new Request({
url: 'command/resume', url: 'command/resume',
method: 'post', method: 'post',
@ -417,9 +436,9 @@ initializeWindows = function() {
}; };
pauseTorrentsByCategoryFN = function (categoryHash) { pauseTorrentsByCategoryFN = function (categoryHash) {
var h = torrentsTable.getFilteredTorrentsHashes('all', categoryHash); var hashes = torrentsTable.getFilteredTorrentsHashes('all', categoryHash);
if (h.length) { if (hashes.length) {
h.each(function (hash, index) { hashes.each(function (hash, index) {
new Request({ new Request({
url: 'command/pause', url: 'command/pause',
method: 'post', method: 'post',
@ -433,13 +452,13 @@ initializeWindows = function() {
}; };
deleteTorrentsByCategoryFN = function (categoryHash) { deleteTorrentsByCategoryFN = function (categoryHash) {
var h = torrentsTable.getFilteredTorrentsHashes('all', categoryHash); var hashes = torrentsTable.getFilteredTorrentsHashes('all', categoryHash);
if (h.length) { if (hashes.length) {
new MochaUI.Window({ new MochaUI.Window({
id: 'confirmDeletionPage', id: 'confirmDeletionPage',
title: "QBT_TR(Deletion confirmation)QBT_TR[CONTEXT=confirmDeletionDlg]", title: "QBT_TR(Deletion confirmation)QBT_TR[CONTEXT=confirmDeletionDlg]",
loadMethod: 'iframe', loadMethod: 'iframe',
contentURL: 'confirmdeletion.html?hashes=' + h.join("|"), contentURL: 'confirmdeletion.html?hashes=' + hashes.join("|"),
scrollbars: false, scrollbars: false,
resizable: false, resizable: false,
maximizable: false, maximizable: false,
@ -494,9 +513,9 @@ initializeWindows = function() {
['pause', 'resume', 'recheck'].each(function(item) { ['pause', 'resume', 'recheck'].each(function(item) {
addClickEvent(item, function(e) { addClickEvent(item, function(e) {
new Event(e).stop(); new Event(e).stop();
var h = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (h.length) { if (hashes.length) {
h.each(function(hash, index) { hashes.each(function(hash, index) {
new Request({ new Request({
url: 'command/' + item, url: 'command/' + item,
method: 'post', method: 'post',
@ -518,13 +537,13 @@ initializeWindows = function() {
}); });
setPriorityFN = function(cmd) { setPriorityFN = function(cmd) {
var h = torrentsTable.selectedRowsIds(); var hashes = torrentsTable.selectedRowsIds();
if (h.length) { if (hashes.length) {
new Request({ new Request({
url: 'command/' + cmd, url: 'command/' + cmd,
method: 'post', method: 'post',
data: { data: {
hashes: h.join("|") hashes: hashes.join("|")
} }
}).send(); }).send();
updateMainData(); updateMainData();

55
src/webui/www/public/setlocation.html

@ -0,0 +1,55 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>QBT_TR(Set location)QBT_TR[CONTEXT=TransferListWidget]</title>
<link rel="stylesheet" href="css/style.css" type="text/css" />
<script type="text/javascript" src="scripts/mootools-1.2-core-yc.js" charset="utf-8"></script>
<script type="text/javascript" src="scripts/mootools-1.2-more.js" charset="utf-8"></script>
<script type="text/javascript">
var setLocationKeyboardEvents = new Keyboard({
defaultEventType: 'keydown',
events: {
'enter': function (event) {
$('setLocationButton').click();
event.preventDefault();
}
}
});
setLocationKeyboardEvents.activate();
window.addEvent('domready', function() {
$('setLocation').focus();
$('setLocationButton').addEvent('click', function(e) {
new Event(e).stop();
// check field
var location = $('setLocation').value.trim();
if (location === null || location === "")
return false;
var hashesList = new URI().getData('hashes');
new Request({
url: 'command/setLocation',
method: 'post',
data: {
hashes: hashesList,
location: location
},
onComplete: function () {
window.parent.closeWindows();
}
}).send();
});
});
</script>
</head>
<body>
<div style="padding: 10px 10px 0px 10px;">
<p style="font-weight: bold;">QBT_TR(Location)QBT_TR[CONTEXT=TransferListWidget]:</p>
<input type="text" id="setLocation" value="" maxlength="100" style="width: 220px;"/>
<div style="text-align: center; padding-top: 10px;">
<input type="button" value="QBT_TR(Save)QBT_TR[CONTEXT=HttpServer]" id="setLocationButton"/>
</div>
</div>
</body>
</html>

26
src/webui/www/public/transferlist.html

@ -22,9 +22,6 @@
targets : '.torrentsTableContextMenuTarget', targets : '.torrentsTableContextMenuTarget',
menu : 'torrentsTableMenu', menu : 'torrentsTableMenu',
actions : { actions : {
Delete : function (element, ref) {
deleteFN();
},
Start : function (element, ref) { Start : function (element, ref) {
startFN(); startFN();
}, },
@ -34,6 +31,15 @@
ForceStart : function (element, ref) { ForceStart : function (element, ref) {
setForceStartFN(); setForceStartFN();
}, },
Delete : function (element, ref) {
deleteFN();
},
SetLocation : function (element, ref) {
setLocationFN();
},
prioTop : function (element, ref) { prioTop : function (element, ref) {
setPriorityFN('topPrio'); setPriorityFN('topPrio');
}, },
@ -46,21 +52,25 @@
prioBottom : function (element, ref) { prioBottom : function (element, ref) {
setPriorityFN('bottomPrio'); setPriorityFN('bottomPrio');
}, },
ForceRecheck : function (element, ref) {
recheckFN(); DownloadLimit : function (element, ref) {
downloadLimitFN();
}, },
UploadLimit : function (element, ref) { UploadLimit : function (element, ref) {
uploadLimitFN(); uploadLimitFN();
}, },
DownloadLimit : function (element, ref) {
downloadLimitFN();
},
SequentialDownload : function (element, ref) { SequentialDownload : function (element, ref) {
toggleSequentialDownloadFN(); toggleSequentialDownloadFN();
}, },
FirstLastPiecePrio : function (element, ref) { FirstLastPiecePrio : function (element, ref) {
toggleFirstLastPiecePrioFN(); toggleFirstLastPiecePrioFN();
}, },
ForceRecheck : function (element, ref) {
recheckFN();
},
SuperSeeding : function (element, ref) { SuperSeeding : function (element, ref) {
setSuperSeedingFN(!ref.getItemChecked('SuperSeeding')); setSuperSeedingFN(!ref.getItemChecked('SuperSeeding'));
} }

Loading…
Cancel
Save