mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-22 04:24:23 +00:00
- Display trackers in torrent properties in Web UI
This commit is contained in:
parent
f04b19ddfa
commit
11a41a1652
@ -33,7 +33,7 @@
|
||||
- FEATURE: Include DHT traffic in the rate limiter (libtorrent >= v0.15 only)
|
||||
- FEATURE: Support for bitcomet padding files (libtorrent >= v0.15 only)
|
||||
- FEATURE: Option to skip file checking and start seeding immediately in torrent addition dialog (Stephanos Antaris) (libtorrent >= v0.15 only)
|
||||
- WEB UI: Removed Web UI to match new qBittorrent UI
|
||||
- WEB UI: Remodeled Web UI to match new qBittorrent UI (Properties and preferences available)
|
||||
- WEB UI: Added internationalization support
|
||||
- WEB UI: Reduced computation in Javascript (do this one server side instead)
|
||||
- COSMETIC: Merged download / upload lists
|
||||
|
@ -44,6 +44,51 @@ QList<QVariantMap> EventManager::getEventList() const {
|
||||
return event_list.values();
|
||||
}
|
||||
|
||||
QList<QVariantMap> EventManager::getPropTrackersInfo(QString hash) const {
|
||||
QList<QVariantMap> trackersInfo;
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(h.is_valid()) {
|
||||
QHash<QString, TrackerInfos> trackers_data = BTSession->getTrackersInfo(hash);
|
||||
std::vector<announce_entry> vect_trackers = h.trackers();
|
||||
std::vector<announce_entry>::iterator it;
|
||||
for(it = vect_trackers.begin(); it != vect_trackers.end(); it++) {
|
||||
QVariantMap tracker;
|
||||
QString tracker_url = misc::toQString(it->url);
|
||||
tracker["url"] = tracker_url;
|
||||
TrackerInfos data = trackers_data.value(tracker_url, TrackerInfos(tracker_url));
|
||||
QString error_message = data.last_message.trimmed();
|
||||
#ifdef LIBTORRENT_0_15
|
||||
if(it->verified) {
|
||||
tracker["status"] = tr("Working");
|
||||
} else {
|
||||
if(it->updating && it->fails == 0) {
|
||||
tracker["status"] = tr("Updating...");
|
||||
} else {
|
||||
if(it->fails > 0) {
|
||||
tracker["status"] = tr("Not working");
|
||||
} else {
|
||||
tracker["status"] = tr("Not contacted yet");
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(data.verified) {
|
||||
tracker["status"] = tr("Working");
|
||||
} else {
|
||||
if(data.fail_count > 0)
|
||||
tracker["status"] = tr("Not working");
|
||||
else
|
||||
tracker["status"] = tr("Not contacted yet");
|
||||
}
|
||||
#endif
|
||||
tracker["num_peers"] = QString::number(trackers_data.value(tracker_url, TrackerInfos(tracker_url)).num_peers);
|
||||
tracker["msg"] = error_message;
|
||||
trackersInfo << tracker;
|
||||
}
|
||||
}
|
||||
return trackersInfo;
|
||||
}
|
||||
|
||||
QVariantMap EventManager::getPropGeneralInfo(QString hash) const {
|
||||
QVariantMap data;
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
|
@ -52,6 +52,7 @@ class EventManager : public QObject
|
||||
EventManager(QObject *parent, Bittorrent* BTSession);
|
||||
QList<QVariantMap> getEventList() const;
|
||||
QVariantMap getPropGeneralInfo(QString hash) const;
|
||||
QList<QVariantMap> getPropTrackersInfo(QString hash) const;
|
||||
|
||||
public slots:
|
||||
void addedTorrent(QTorrentHandle& h);
|
||||
|
@ -102,7 +102,7 @@ void HttpConnection::write()
|
||||
}
|
||||
|
||||
QString HttpConnection::translateDocument(QString data) {
|
||||
std::string contexts[] = {"TransferListFiltersWidget", "TransferListWidget", "PropertiesWidget", "GUI", "MainWindow", "HttpServer", "confirmDeletionDlg"};
|
||||
std::string contexts[] = {"TransferListFiltersWidget", "TransferListWidget", "PropertiesWidget", "GUI", "MainWindow", "HttpServer", "confirmDeletionDlg", "TrackerList"};
|
||||
int i=0;
|
||||
bool found = false;
|
||||
do {
|
||||
@ -117,7 +117,7 @@ QString HttpConnection::translateDocument(QString data) {
|
||||
do {
|
||||
translation = qApp->translate(contexts[context_index].c_str(), word.toLocal8Bit().data(), 0, QCoreApplication::UnicodeUTF8, 1);
|
||||
++context_index;
|
||||
}while(translation == word && context_index < 7);
|
||||
}while(translation == word && context_index < 8);
|
||||
//qDebug("Translation is %s", translation.toUtf8().data());
|
||||
data = data.replace(i, regex.matchedLength(), translation);
|
||||
i += translation.length();
|
||||
@ -162,6 +162,12 @@ void HttpConnection::respond()
|
||||
respondGenPropertiesJson(hash);
|
||||
return;
|
||||
}
|
||||
if(list[1] == "propertiesTrackers") {
|
||||
qDebug("Web UI asked for trackers");
|
||||
QString hash = list[2];
|
||||
respondTrackersPropertiesJson(hash);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (list[0] == "command")
|
||||
@ -226,6 +232,16 @@ void HttpConnection::respondGenPropertiesJson(QString hash) {
|
||||
write();
|
||||
}
|
||||
|
||||
void HttpConnection::respondTrackersPropertiesJson(QString hash) {
|
||||
EventManager* manager = parent->eventManager();
|
||||
QString string = json::toJson(manager->getPropTrackersInfo(hash));
|
||||
generator.setStatusLine(200, "OK");
|
||||
generator.setContentTypeByExt("js");
|
||||
generator.setMessage(string);
|
||||
write();
|
||||
}
|
||||
|
||||
|
||||
void HttpConnection::respondCommand(QString command)
|
||||
{
|
||||
if(command == "download")
|
||||
|
@ -57,6 +57,7 @@ class HttpConnection : public QObject
|
||||
virtual void respond();
|
||||
void respondJson();
|
||||
void respondGenPropertiesJson(QString hash);
|
||||
void respondTrackersPropertiesJson(QString hash);
|
||||
void respondCommand(QString command);
|
||||
void respondNotFound();
|
||||
void processDownloadedFile(QString, QString);
|
||||
|
@ -174,7 +174,7 @@ public slots:
|
||||
std::vector<announce_entry>::iterator it;
|
||||
for(it = trackers.begin(); it != trackers.end(); it++) {
|
||||
QStringList item_list;
|
||||
QString tracker_url = misc::toQString((*it).url);
|
||||
QString tracker_url = misc::toQString(it->url);
|
||||
QTreeWidgetItem *item = tracker_items.value(tracker_url, 0);
|
||||
if(!item) {
|
||||
item = new QTreeWidgetItem();
|
||||
@ -187,13 +187,13 @@ public slots:
|
||||
TrackerInfos data = trackers_data.value(tracker_url, TrackerInfos(tracker_url));
|
||||
QString error_message = data.last_message.trimmed();
|
||||
#ifdef LIBTORRENT_0_15
|
||||
if((*it).verified) {
|
||||
if(it->verified) {
|
||||
item->setText(COL_STATUS, tr("Working"));
|
||||
} else {
|
||||
if((*it).updating && (*it).fails == 0) {
|
||||
if(it->updating && it->fails == 0) {
|
||||
item->setText(COL_STATUS, tr("Updating..."));
|
||||
} else {
|
||||
if((*it).fails > 0) {
|
||||
if(it->fails > 0) {
|
||||
item->setText(COL_STATUS, tr("Not working"));
|
||||
} else {
|
||||
item->setText(COL_STATUS, tr("Not contacted yet"));
|
||||
|
@ -7,35 +7,42 @@
|
||||
|
||||
**************************************************************/
|
||||
|
||||
#properties #trackers table,
|
||||
#transferList table {
|
||||
border: 1px solid #ccc;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#properties #trackers th,
|
||||
#transferList th {
|
||||
background-color: #eee;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
#properties #trackers tr,
|
||||
#transferList tr {
|
||||
background-color: #fff;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
#properties #trackers tr.alt,
|
||||
#transferList tr.alt {
|
||||
background-color: #eee;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
#properties #trackers td,
|
||||
#transferList td {
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
#properties #trackers tr.selected,
|
||||
#transferList tr.selected {
|
||||
background-color: #354158;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#properties #trackers tr.over,
|
||||
#transferList tr.over {
|
||||
background-color: #ee6600;
|
||||
color: #fff;
|
||||
|
@ -51,10 +51,14 @@ dynamic information: total_downloaded, total_uploaded, total_wasted, up_limit, d
|
||||
}
|
||||
|
||||
var loadData = function() {
|
||||
if(!$defined($('torrent_hash'))) {
|
||||
// Tab changed
|
||||
return;
|
||||
}
|
||||
var current_hash = myTable.getCurrentTorrentHash();
|
||||
if(current_hash == "") {
|
||||
clearData();
|
||||
loadData.delay(2000);
|
||||
loadData.delay(1500);
|
||||
return;
|
||||
}
|
||||
// Display hash
|
||||
@ -89,7 +93,7 @@ dynamic information: total_downloaded, total_uploaded, total_wasted, up_limit, d
|
||||
clearData();
|
||||
}
|
||||
waiting=false;
|
||||
loadData.delay(2000);
|
||||
loadData.delay(1500);
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
|
@ -1 +1,127 @@
|
||||
CONTENT
|
||||
<span id="trackers">
|
||||
<table class="torrentTable" cellpadding="0" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>_(URL)</th>
|
||||
<th>_(Status)</th>
|
||||
<th>_(Peers)</th>
|
||||
<th>_(Message)</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="trackersTable"></tbody>
|
||||
</table>
|
||||
</span>
|
||||
|
||||
<script type="text/javascript">
|
||||
var trackersDynTable = 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 waitingTrackers=false;
|
||||
var current_hash = "";
|
||||
|
||||
var loadTrackersData = function() {
|
||||
if(!$defined($('trackersTable'))) {
|
||||
// Tab changed
|
||||
return;
|
||||
}
|
||||
var new_hash = myTable.getCurrentTorrentHash();
|
||||
if(new_hash == "") {
|
||||
tTable.removeAllRows();
|
||||
loadTrackersData.delay(1500);
|
||||
return;
|
||||
}
|
||||
if(new_hash != current_hash) {
|
||||
tTable.removeAllRows();
|
||||
current_hash = new_hash;
|
||||
}
|
||||
var url = 'json/propertiesTrackers/'+current_hash;
|
||||
if (!waitingTrackers) {
|
||||
waitingTrackers=true;
|
||||
var request = new Request.JSON({
|
||||
url: url,
|
||||
method: 'get',
|
||||
onFailure: function() {
|
||||
$('error_div').set('html', 'qBittorrent client is not reachable');
|
||||
waitingTrackers=false;
|
||||
loadTrackersData.delay(2000);
|
||||
},
|
||||
onSuccess: function(trackers) {
|
||||
$('error_div').set('html', '');
|
||||
if(trackers){
|
||||
// Update Trackers data
|
||||
trackers.each(function(tracker){
|
||||
var row = new Array();
|
||||
row.length = 4;
|
||||
row[0] = tracker.url;
|
||||
row[1] = tracker.status;
|
||||
row[2] = tracker.num_peers;
|
||||
row[3] = tracker.msg;
|
||||
tTable.insertRow(row);
|
||||
});
|
||||
} else {
|
||||
tTable.removeAllRows();
|
||||
}
|
||||
waitingTrackers=false;
|
||||
loadTrackersData.delay(1500);
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
|
||||
}
|
||||
tTable = new trackersDynTable();
|
||||
tTable.setup($('trackersTable'));
|
||||
// Initial loading
|
||||
loadTrackersData();
|
||||
</script>
|
||||
|
@ -38,12 +38,11 @@ var dynamicTable = new Class ({
|
||||
|
||||
setup: function(table, progressIndex){
|
||||
this.table = $(table);
|
||||
this.rows = new Object();
|
||||
this.rows = new Hash();
|
||||
this.cur = new Array();
|
||||
this.priority_hidden = false;
|
||||
this.progressIndex = progressIndex;
|
||||
this.filter = 'all';
|
||||
this.current_hash = '';
|
||||
},
|
||||
|
||||
getCurrentTorrentHash: function() {
|
||||
@ -127,12 +126,11 @@ var dynamicTable = new Class ({
|
||||
},
|
||||
|
||||
insertRow: function(id, row, status){
|
||||
var tr = this.rows[id];
|
||||
if($defined(tr))
|
||||
return;
|
||||
//this.removeRow(id);
|
||||
if(this.rows.has(id)) {
|
||||
return;
|
||||
}
|
||||
var tr = new Element('tr');
|
||||
this.rows[id] = tr;
|
||||
this.rows.set(id, tr);
|
||||
for(var i=0; i<row.length; i++)
|
||||
{
|
||||
var td = new Element('td');
|
||||
@ -158,15 +156,15 @@ var dynamicTable = new Class ({
|
||||
// remove it
|
||||
this.cur.erase(id);
|
||||
// Remove selected style
|
||||
temptr = this.rows[id];
|
||||
if(temptr){
|
||||
temptr.removeClass('selected');
|
||||
}
|
||||
if(this.rows.has(id)) {
|
||||
temptr = this.rows.get(id);
|
||||
temptr.removeClass('selected');
|
||||
}
|
||||
} else {
|
||||
this.cur[this.cur.length] = id;
|
||||
// Add selected style
|
||||
temptr = this.rows[id];
|
||||
if(temptr){
|
||||
if(this.rows.has(id)) {
|
||||
temptr = this.rows.get(id);
|
||||
temptr.addClass('selected');
|
||||
}
|
||||
}
|
||||
@ -186,8 +184,8 @@ var dynamicTable = new Class ({
|
||||
curID = ids[i];
|
||||
this.cur[this.cur.length] = curID;
|
||||
// Add selected style
|
||||
temptr = this.rows[curID];
|
||||
if(temptr){
|
||||
if(this.rows.has(curID)) {
|
||||
temptr = this.rows.get(curID);
|
||||
temptr.addClass('selected');
|
||||
}
|
||||
}
|
||||
@ -195,15 +193,15 @@ var dynamicTable = new Class ({
|
||||
// Simple selection
|
||||
// Remove selected style from previous ones
|
||||
for(i=0; i<this.cur.length; i++) {
|
||||
var temptr = this.rows[this.cur[i]];
|
||||
if(temptr){
|
||||
if(this.rows.has(this.cur[i])) {
|
||||
var temptr = this.rows.get(this.cur[i]);
|
||||
temptr.removeClass('selected');
|
||||
}
|
||||
}
|
||||
this.cur.empty();
|
||||
// Add selected style to new one
|
||||
temptr = this.rows[id];
|
||||
if(temptr){
|
||||
if(this.rows.has(id)) {
|
||||
temptr = this.rows.get(id);
|
||||
temptr.addClass('selected');
|
||||
}
|
||||
this.cur[0] = id;
|
||||
@ -212,44 +210,40 @@ var dynamicTable = new Class ({
|
||||
}
|
||||
return false;
|
||||
}.bind(this));
|
||||
|
||||
// Apply filter
|
||||
this.applyFilterOnRow(tr, status);
|
||||
// Insert
|
||||
tr.injectInside(this.table);
|
||||
this.altRow();
|
||||
// Apply filter
|
||||
//this.applyFilterOnRow(tr, status);
|
||||
},
|
||||
|
||||
selectAll: function() {
|
||||
this.cur.empty();
|
||||
for (var id in this.rows) {
|
||||
this.rows.each(function(tr, id){
|
||||
this.cur[this.cur.length] = id;
|
||||
temptr = this.rows[id];
|
||||
if(temptr){
|
||||
if(!temptr.hasClass('selected')) {
|
||||
temptr.addClass('selected');
|
||||
}
|
||||
if(!tr.hasClass('selected')) {
|
||||
tr.addClass('selected');
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateRow: function(id, row, status){
|
||||
var tr = this.rows[id];
|
||||
if($defined(tr))
|
||||
{
|
||||
// Apply filter
|
||||
this.applyFilterOnRow(tr, status);
|
||||
var tds = tr.getElements('td');
|
||||
for(var i=0; i<row.length; i++) {
|
||||
if(i==this.progressIndex) {
|
||||
tds[i].set('html', '');
|
||||
tds[i].adopt(new ProgressBar(row[i].toFloat(), {width:80}));
|
||||
} else {
|
||||
tds[i].set('html', row[i]);
|
||||
}
|
||||
};
|
||||
return true;
|
||||
if(!this.rows.has(id)) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
var tr = this.rows.get(id);
|
||||
// Apply filter
|
||||
this.applyFilterOnRow(tr, status);
|
||||
var tds = tr.getElements('td');
|
||||
for(var i=0; i<row.length; i++) {
|
||||
if(i==this.progressIndex) {
|
||||
tds[i].set('html', '');
|
||||
tds[i].adopt(new ProgressBar(row[i].toFloat(), {width:80}));
|
||||
} else {
|
||||
tds[i].set('html', row[i]);
|
||||
}
|
||||
};
|
||||
return true;
|
||||
},
|
||||
|
||||
removeRow: function(id){
|
||||
@ -257,11 +251,11 @@ var dynamicTable = new Class ({
|
||||
{
|
||||
this.cur.erase(id);
|
||||
}
|
||||
var tr = this.rows[id];
|
||||
if($defined(tr))
|
||||
{
|
||||
if(this.rows.has(id)) {
|
||||
var tr = this.rows.get(id);
|
||||
tr.dispose();
|
||||
this.altRow();
|
||||
this.rows.erase(id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -274,10 +268,10 @@ var dynamicTable = new Class ({
|
||||
getRowIds: function(){
|
||||
var ids = new Array();
|
||||
var i = 0;
|
||||
for (var id in this.rows) {
|
||||
this.rows.each(function(tr, id) {
|
||||
ids[i] = id;
|
||||
i++
|
||||
}
|
||||
i++;
|
||||
}.bind(this));
|
||||
return ids;
|
||||
}
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user