[Web UI] Add Web Seeds (HTTP Sources) tab

This commit is contained in:
ngosang 2015-06-12 17:52:01 +02:00
parent f12b300298
commit 8e4b9f30bb
10 changed files with 175 additions and 2 deletions

View file

@ -110,6 +110,9 @@ static const char KEY_TRACKER_STATUS[] = "status";
static const char KEY_TRACKER_MSG[] = "msg"; static const char KEY_TRACKER_MSG[] = "msg";
static const char KEY_TRACKER_PEERS[] = "num_peers"; static const char KEY_TRACKER_PEERS[] = "num_peers";
// Web seed keys
static const char KEY_WEBSEED_URL[] = "url";
// Torrent keys (Properties) // Torrent keys (Properties)
static const char KEY_PROP_SAVE_PATH[] = "save_path"; static const char KEY_PROP_SAVE_PATH[] = "save_path";
static const char KEY_PROP_CREATION_DATE[] = "creation_date"; static const char KEY_PROP_CREATION_DATE[] = "creation_date";
@ -377,6 +380,31 @@ QByteArray btjson::getTrackersForTorrent(const QString& hash)
return json::toJson(tracker_list); return json::toJson(tracker_list);
} }
/**
* Returns the web seeds for a torrent in JSON format.
*
* The return value is a JSON-formatted list of dictionaries.
* The dictionary keys are:
* - "url": Web seed URL
*/
QByteArray btjson::getWebSeedsForTorrent(const QString& hash)
{
CACHED_VARIABLE_FOR_HASH(QVariantList, webSeedList, CACHE_DURATION_MS, hash);
BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(hash);
if (!torrent) {
qWarning() << Q_FUNC_INFO << "Invalid torrent " << qPrintable(hash);
return QByteArray();
}
foreach (const QUrl &webseed, torrent->urlSeeds()) {
QVariantMap webSeedDict;
webSeedDict[KEY_WEBSEED_URL] = webseed.toString();
webSeedList.append(webSeedDict);
}
return json::toJson(webSeedList);
}
/** /**
* Returns the properties for a torrent in JSON format. * Returns the properties for a torrent in JSON format.
* *

View file

@ -47,6 +47,7 @@ public:
QString sortedColumn = "name", bool reverse = false, int limit = 0, int offset = 0); QString sortedColumn = "name", bool reverse = false, int limit = 0, int offset = 0);
static QByteArray getSyncMainData(int acceptedResponseId, QVariantMap &lastData, QVariantMap &lastAcceptedData); static QByteArray getSyncMainData(int acceptedResponseId, QVariantMap &lastData, QVariantMap &lastAcceptedData);
static QByteArray getTrackersForTorrent(const QString& hash); static QByteArray getTrackersForTorrent(const QString& hash);
static QByteArray getWebSeedsForTorrent(const QString& hash);
static QByteArray getPropertiesForTorrent(const QString& hash); static QByteArray getPropertiesForTorrent(const QString& hash);
static QByteArray getFilesForTorrent(const QString& hash); static QByteArray getFilesForTorrent(const QString& hash);
static QByteArray getTransferInfo(); static QByteArray getTransferInfo();

View file

@ -76,6 +76,7 @@ QMap<QString, QMap<QString, WebApplication::Action> > WebApplication::initialize
ADD_ACTION(query, transferInfo); ADD_ACTION(query, transferInfo);
ADD_ACTION(query, propertiesGeneral); ADD_ACTION(query, propertiesGeneral);
ADD_ACTION(query, propertiesTrackers); ADD_ACTION(query, propertiesTrackers);
ADD_ACTION(query, propertiesWebSeeds);
ADD_ACTION(query, propertiesFiles); ADD_ACTION(query, propertiesFiles);
ADD_ACTION(sync, maindata); ADD_ACTION(sync, maindata);
ADD_ACTION(command, shutdown); ADD_ACTION(command, shutdown);
@ -249,6 +250,12 @@ void WebApplication::action_query_propertiesTrackers()
print(btjson::getTrackersForTorrent(args_.front()), Http::CONTENT_TYPE_JS); print(btjson::getTrackersForTorrent(args_.front()), Http::CONTENT_TYPE_JS);
} }
void WebApplication::action_query_propertiesWebSeeds()
{
CHECK_URI(1);
print(btjson::getWebSeedsForTorrent(args_.front()), Http::CONTENT_TYPE_JS);
}
void WebApplication::action_query_propertiesFiles() void WebApplication::action_query_propertiesFiles()
{ {
CHECK_URI(1); CHECK_URI(1);

View file

@ -52,6 +52,7 @@ private:
void action_query_transferInfo(); void action_query_transferInfo();
void action_query_propertiesGeneral(); void action_query_propertiesGeneral();
void action_query_propertiesTrackers(); void action_query_propertiesTrackers();
void action_query_propertiesWebSeeds();
void action_query_propertiesFiles(); void action_query_propertiesFiles();
void action_sync_maindata(); void action_sync_maindata();
void action_command_shutdown(); void action_command_shutdown();

View file

@ -33,6 +33,7 @@
<file>www/public/properties_content.html</file> <file>www/public/properties_content.html</file>
<file>www/public/scripts/prop-general.js</file> <file>www/public/scripts/prop-general.js</file>
<file>www/public/scripts/prop-trackers.js</file> <file>www/public/scripts/prop-trackers.js</file>
<file>www/public/scripts/prop-webseeds.js</file>
<file>www/public/scripts/prop-files.js</file> <file>www/public/scripts/prop-files.js</file>
<file>www/public/transferlist.html</file> <file>www/public/transferlist.html</file>
<file>www/public/upload.html</file> <file>www/public/upload.html</file>

View file

@ -362,7 +362,7 @@ ul.filterList li:hover a {
line-height: 20px; line-height: 20px;
} }
#trackersTable { #trackersTable, #webseedsTable {
line-height: 25px; line-height: 25px;
} }

View file

@ -2,6 +2,7 @@
<ul id="propertiesTabs" class="tab-menu"> <ul id="propertiesTabs" class="tab-menu">
<li id="PropGeneralLink" class="selected"><a>QBT_TR(General)QBT_TR</a></li> <li id="PropGeneralLink" class="selected"><a>QBT_TR(General)QBT_TR</a></li>
<li id="PropTrackersLink"><a>QBT_TR(Trackers)QBT_TR</a></li> <li id="PropTrackersLink"><a>QBT_TR(Trackers)QBT_TR</a></li>
<li id="PropWebSeedsLink"><a>QBT_TR(HTTP Sources)QBT_TR</a></li>
<li id="PropFilesLink"><a>QBT_TR(Content)QBT_TR</a></li> <li id="PropFilesLink"><a>QBT_TR(Content)QBT_TR</a></li>
</ul> </ul>
<div class="clear"></div> <div class="clear"></div>

View file

@ -38,6 +38,19 @@
</div> </div>
</div> </div>
<div id="prop_webseeds" class="invisible">
<div id="webseeds">
<table class="torrentTable" cellpadding="0" cellspacing="0" style="width: 100%">
<thead>
<tr>
<th>QBT_TR(URL)QBT_TR</th>
</tr>
</thead>
<tbody id="webseedsTable"></tbody>
</table>
</div>
</div>
<div id="prop_files" class="invisible"> <div id="prop_files" class="invisible">
<div id="torrentFiles"> <div id="torrentFiles">
<table class="torrentTable" cellpadding="0" cellspacing="0" style="width: 100%"> <table class="torrentTable" cellpadding="0" cellspacing="0" style="width: 100%">

View file

@ -344,7 +344,7 @@ window.addEvent('load', function () {
contentURL : 'properties_content.html', contentURL : 'properties_content.html',
require : { require : {
css : ['css/Tabs.css'], css : ['css/Tabs.css'],
js : ['scripts/prop-general.js', 'scripts/prop-trackers.js', 'scripts/prop-files.js'], js : ['scripts/prop-general.js', 'scripts/prop-trackers.js', 'scripts/prop-webseeds.js', 'scripts/prop-files.js'],
}, },
tabsURL : 'properties.html', tabsURL : 'properties.html',
tabsOnload : function() { tabsOnload : function() {
@ -355,6 +355,8 @@ window.addEvent('load', function () {
updateTorrentData(); updateTorrentData();
else if (!$('prop_trackers').hasClass('invisible')) else if (!$('prop_trackers').hasClass('invisible'))
updateTrackersData(); updateTrackersData();
else if (!$('prop_webseeds').hasClass('invisible'))
updateWebSeedsData();
else if (!$('prop_files').hasClass('invisible')) else if (!$('prop_files').hasClass('invisible'))
updateTorrentFilesData(); updateTorrentFilesData();
} }
@ -362,6 +364,7 @@ window.addEvent('load', function () {
$('PropGeneralLink').addEvent('click', function(e){ $('PropGeneralLink').addEvent('click', function(e){
$('prop_general').removeClass("invisible"); $('prop_general').removeClass("invisible");
$('prop_trackers').addClass("invisible"); $('prop_trackers').addClass("invisible");
$('prop_webseeds').addClass("invisible");
$('prop_files').addClass("invisible"); $('prop_files').addClass("invisible");
updatePropertiesPanel(); updatePropertiesPanel();
}); });
@ -369,6 +372,15 @@ window.addEvent('load', function () {
$('PropTrackersLink').addEvent('click', function(e){ $('PropTrackersLink').addEvent('click', function(e){
$('prop_trackers').removeClass("invisible"); $('prop_trackers').removeClass("invisible");
$('prop_general').addClass("invisible"); $('prop_general').addClass("invisible");
$('prop_webseeds').addClass("invisible");
$('prop_files').addClass("invisible");
updatePropertiesPanel();
});
$('PropWebSeedsLink').addEvent('click', function(e){
$('prop_webseeds').removeClass("invisible");
$('prop_general').addClass("invisible");
$('prop_trackers').addClass("invisible");
$('prop_files').addClass("invisible"); $('prop_files').addClass("invisible");
updatePropertiesPanel(); updatePropertiesPanel();
}); });
@ -377,6 +389,7 @@ window.addEvent('load', function () {
$('prop_files').removeClass("invisible"); $('prop_files').removeClass("invisible");
$('prop_general').addClass("invisible"); $('prop_general').addClass("invisible");
$('prop_trackers').addClass("invisible"); $('prop_trackers').addClass("invisible");
$('prop_webseeds').addClass("invisible");
updatePropertiesPanel(); updatePropertiesPanel();
}); });
}, },

View file

@ -0,0 +1,108 @@
var webseedsDynTable = new Class({
initialize: function() {},
setup: function(table) {
this.table = $(table);
this.rows = new Hash();
},
removeRow: function(url) {
if (this.rows.has(url)) {
var tr = this.rows.get(url);
tr.dispose();
this.rows.erase(url);
return true;
}
return false;
},
removeAllRows: function() {
this.rows.each(function(tr, url) {
this.removeRow(url);
}.bind(this));
},
updateRow: function(tr, row) {
var tds = tr.getElements('td');
for (var i = 0; i < row.length; i++) {
tds[i].set('html', row[i]);
}
return true;
},
insertRow: function(row) {
var url = row[0];
if (this.rows.has(url)) {
var tr = this.rows.get(url);
this.updateRow(tr, row);
return;
}
//this.removeRow(id);
var tr = new Element('tr');
this.rows.set(url, tr);
for (var i = 0; i < row.length; i++) {
var td = new Element('td');
td.set('html', row[i]);
td.injectInside(tr);
}
tr.injectInside(this.table);
},
});
var current_hash = "";
var loadWebSeedsDataTimer;
var loadWebSeedsData = function() {
if ($('prop_webseeds').hasClass('invisible')) {
// Tab changed, don't do anything
return;
}
var new_hash = myTable.getCurrentTorrentHash();
if (new_hash == "") {
wsTable.removeAllRows();
clearTimeout(loadWebSeedsDataTimer);
loadWebSeedsDataTimer = loadWebSeedsData.delay(10000);
return;
}
if (new_hash != current_hash) {
wsTable.removeAllRows();
current_hash = new_hash;
}
var url = 'query/propertiesWebSeeds/' + current_hash;
var request = new Request.JSON({
url: url,
noCache: true,
method: 'get',
onFailure: function() {
$('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR');
clearTimeout(loadWebSeedsDataTimer);
loadWebSeedsDataTimer = loadWebSeedsData.delay(20000);
},
onSuccess: function(webseeds) {
$('error_div').set('html', '');
if (webseeds) {
// Update WebSeeds data
webseeds.each(function(webseed) {
var row = new Array();
row.length = 1;
row[0] = webseed.url;
wsTable.insertRow(row);
});
}
else {
wsTable.removeAllRows();
}
clearTimeout(loadWebSeedsDataTimer);
loadWebSeedsDataTimer = loadWebSeedsData.delay(10000);
}
}).send();
}
var updateWebSeedsData = function() {
clearTimeout(loadWebSeedsDataTimer);
loadWebSeedsData();
}
wsTable = new webseedsDynTable();
wsTable.setup($('webseedsTable'));