mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-11-27 03:39:39 +03:00
- Web UI: Display generation information in torrent properties
This commit is contained in:
parent
ce6f665a7b
commit
e35d100769
8 changed files with 210 additions and 53 deletions
|
@ -32,6 +32,7 @@
|
|||
#include "eventmanager.h"
|
||||
#include "bittorrent.h"
|
||||
#include "misc.h"
|
||||
#include "torrentpersistentdata.h"
|
||||
#include <QDebug>
|
||||
|
||||
EventManager::EventManager(QObject *parent, Bittorrent *BTSession)
|
||||
|
@ -43,6 +44,51 @@ QList<QVariantMap> EventManager::getEventList() const {
|
|||
return event_list.values();
|
||||
}
|
||||
|
||||
QVariantMap EventManager::getPropGeneralInfo(QString hash) const {
|
||||
QVariantMap data;
|
||||
QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||
if(h.is_valid()) {
|
||||
// Save path
|
||||
data["save_path"] = TorrentPersistentData::getSavePath(hash);
|
||||
// Creation date
|
||||
data["creation_date"] = h.creation_date();
|
||||
// Comment
|
||||
data["comment"] = h.comment();
|
||||
data["total_wasted"] = misc::friendlyUnit(h.total_failed_bytes()+h.total_redundant_bytes());
|
||||
data["total_uploaded"] = misc::friendlyUnit(h.all_time_upload()) + " ("+misc::friendlyUnit(h.total_payload_upload())+" "+tr("this session")+")";
|
||||
data["total_downloaded"] = misc::friendlyUnit(h.all_time_download()) + " ("+misc::friendlyUnit(h.total_payload_download())+" "+tr("this session")+")";
|
||||
if(h.upload_limit() <= 0)
|
||||
data["up_limit"] = QString::fromUtf8("∞");
|
||||
else
|
||||
data["up_limit"] = misc::friendlyUnit(h.upload_limit())+tr("/s", "/second (i.e. per second)");
|
||||
if(h.download_limit() <= 0)
|
||||
data["dl_limit"] = QString::fromUtf8("∞");
|
||||
else
|
||||
data["dl_limit"] = misc::friendlyUnit(h.download_limit())+tr("/s", "/second (i.e. per second)");
|
||||
QString elapsed_txt = misc::userFriendlyDuration(h.active_time());
|
||||
if(h.is_seed()) {
|
||||
elapsed_txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(misc::userFriendlyDuration(h.seeding_time()))+")";
|
||||
}
|
||||
data["time_elapsed"] = elapsed_txt;
|
||||
data["nb_connections"] = QString::number(h.num_connections())+" ("+tr("%1 max", "e.g. 10 max").arg(QString::number(h.connections_limit()))+")";
|
||||
// Update ratio info
|
||||
float ratio;
|
||||
if(h.total_payload_download() == 0){
|
||||
if(h.total_payload_upload() == 0)
|
||||
ratio = 1.;
|
||||
else
|
||||
ratio = 10.; // Max ratio
|
||||
}else{
|
||||
ratio = (double)h.total_payload_upload()/(double)h.total_payload_download();
|
||||
if(ratio > 10.){
|
||||
ratio = 10.;
|
||||
}
|
||||
}
|
||||
data["share_ratio"] = QString(QByteArray::number(ratio, 'f', 1));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void EventManager::addedTorrent(QTorrentHandle& h)
|
||||
{
|
||||
modifiedTorrent(h);
|
||||
|
|
|
@ -51,6 +51,7 @@ class EventManager : public QObject
|
|||
public:
|
||||
EventManager(QObject *parent, Bittorrent* BTSession);
|
||||
QList<QVariantMap> getEventList() const;
|
||||
QVariantMap getPropGeneralInfo(QString hash) const;
|
||||
|
||||
public slots:
|
||||
void addedTorrent(QTorrentHandle& h);
|
||||
|
|
|
@ -147,7 +147,7 @@ void HttpConnection::respond()
|
|||
}
|
||||
if (list.size() == 0)
|
||||
list.append("index.html");
|
||||
if (list.size() == 2)
|
||||
if (list.size() >= 2)
|
||||
{
|
||||
if (list[0] == "json")
|
||||
{
|
||||
|
@ -156,6 +156,14 @@ void HttpConnection::respond()
|
|||
respondJson();
|
||||
return;
|
||||
}
|
||||
if(list.size() > 2) {
|
||||
if(list[1] == "propertiesGeneral") {
|
||||
qDebug("Web UI Asked for general properties data");
|
||||
QString hash = list[2];
|
||||
respondGenPropertiesJson(hash);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (list[0] == "command")
|
||||
{
|
||||
|
@ -210,6 +218,17 @@ void HttpConnection::respondJson()
|
|||
write();
|
||||
}
|
||||
|
||||
void HttpConnection::respondGenPropertiesJson(QString hash) {
|
||||
qDebug("Torrent hash is %s", hash.toLocal8Bit().data());
|
||||
EventManager* manager = parent->eventManager();
|
||||
QString string = json::toJson(manager->getPropGeneralInfo(hash));
|
||||
qDebug("GenProperties JSON is %s", string.toLocal8Bit().data());
|
||||
generator.setStatusLine(200, "OK");
|
||||
generator.setContentTypeByExt("js");
|
||||
generator.setMessage(string);
|
||||
write();
|
||||
}
|
||||
|
||||
void HttpConnection::respondCommand(QString command)
|
||||
{
|
||||
if(command == "download")
|
||||
|
|
|
@ -56,6 +56,7 @@ class HttpConnection : public QObject
|
|||
void write();
|
||||
virtual void respond();
|
||||
void respondJson();
|
||||
void respondGenPropertiesJson(QString hash);
|
||||
void respondCommand(QString command);
|
||||
void respondNotFound();
|
||||
void processDownloadedFile(QString, QString);
|
||||
|
|
94
src/json.h
94
src/json.h
|
@ -36,71 +36,79 @@
|
|||
|
||||
namespace json {
|
||||
|
||||
QString toJson(QVariant v) {
|
||||
if (v.isNull())
|
||||
return "null";
|
||||
switch(v.type())
|
||||
{
|
||||
QString toJson(QVariant v) {
|
||||
if (v.isNull())
|
||||
return "null";
|
||||
switch(v.type())
|
||||
{
|
||||
case QVariant::Bool:
|
||||
case QVariant::Double:
|
||||
case QVariant::Int:
|
||||
case QVariant::LongLong:
|
||||
case QVariant::UInt:
|
||||
case QVariant::ULongLong:
|
||||
return v.value<QString>();
|
||||
return v.value<QString>();
|
||||
case QVariant::String:
|
||||
{
|
||||
QString s = v.value<QString>();
|
||||
QString result = "\"";
|
||||
for(int i=0; i<s.size(); i++)
|
||||
{
|
||||
QChar ch = s[i];
|
||||
switch(ch.toAscii())
|
||||
{
|
||||
{
|
||||
QString s = v.value<QString>();
|
||||
QString result = "\"";
|
||||
for(int i=0; i<s.size(); i++)
|
||||
{
|
||||
QChar ch = s[i];
|
||||
switch(ch.toAscii())
|
||||
{
|
||||
case '\b':
|
||||
result += "\\b";
|
||||
break;
|
||||
result += "\\b";
|
||||
break;
|
||||
case '\f':
|
||||
result += "\\f";
|
||||
break;
|
||||
result += "\\f";
|
||||
break;
|
||||
case '\n':
|
||||
result += "\\n";
|
||||
break;
|
||||
result += "\\n";
|
||||
break;
|
||||
case '\r':
|
||||
result += "\\r";
|
||||
break;
|
||||
result += "\\r";
|
||||
break;
|
||||
case '\t':
|
||||
result += "\\t";
|
||||
break;
|
||||
result += "\\t";
|
||||
break;
|
||||
case '\"':
|
||||
case '\'':
|
||||
case '\\':
|
||||
case '&':
|
||||
result += '\\';
|
||||
result += '\\';
|
||||
case '\0':
|
||||
default:
|
||||
result += ch;
|
||||
}
|
||||
}
|
||||
result += "\"";
|
||||
return result;
|
||||
}
|
||||
result += ch;
|
||||
}
|
||||
}
|
||||
result += "\"";
|
||||
return result;
|
||||
}
|
||||
default:
|
||||
return "undefined";
|
||||
}
|
||||
return "undefined";
|
||||
}
|
||||
}
|
||||
|
||||
QString toJson(QList<QVariantMap> v) {
|
||||
QStringList res;
|
||||
foreach(QVariantMap m, v) {
|
||||
QStringList vlist;
|
||||
foreach(QString key, m.keys()) {
|
||||
vlist << toJson(key)+":"+toJson(m[key]);
|
||||
}
|
||||
res << "{"+vlist.join(",")+"}";
|
||||
}
|
||||
return "["+res.join(",")+"]";
|
||||
QString toJson(QVariantMap m) {
|
||||
QStringList vlist;
|
||||
foreach(QString key, m.keys()) {
|
||||
vlist << toJson(key)+":"+toJson(m[key]);
|
||||
}
|
||||
return "{"+vlist.join(",")+"}";
|
||||
}
|
||||
|
||||
QString toJson(QList<QVariantMap> v) {
|
||||
QStringList res;
|
||||
foreach(QVariantMap m, v) {
|
||||
QStringList vlist;
|
||||
foreach(QString key, m.keys()) {
|
||||
vlist << toJson(key)+":"+toJson(m[key]);
|
||||
}
|
||||
res << "{"+vlist.join(",")+"}";
|
||||
}
|
||||
return "["+res.join(",")+"]";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,26 +1,100 @@
|
|||
<fieldset>
|
||||
<legend><b>_(Transfer)</b></legend>
|
||||
<table>
|
||||
<tr><td style="text-align:right; padding: 4px;">_(Uploaded:)</td><td>0 Kb</td></tr>
|
||||
<tr><td style="text-align:right; padding: 4px;">_(Downloaded:)</td><td>0 Kb</td></tr>
|
||||
<tr><td style="text-align:right; padding: 4px;">_(Wasted:)</td><td>0 Kb</td></tr>
|
||||
<tr><td style="text-align:right; padding: 4px;">_(Uploaded:)</td><td style="padding-right: 20px;" id="total_uploaded">0 Kb</td><td style="text-align:right; padding: 4px;">_(UP limit:)</td><td style="padding-right: 20px;" id="up_limit">xx</td><td style="text-align:right; padding: 4px;">_(Share ratio:)</td><td id="share_ratio">xx</td></tr>
|
||||
<tr><td style="text-align:right; padding: 4px;">_(Downloaded:)</td><td style="padding-right: 20px;" id="total_downloaded">0 Kb</td><td style="text-align:right; padding: 4px;">_(DL limit:)</td><td style="padding-right: 20px;" id="dl_limit">xx</td><td style="text-align:right; padding: 4px;">_(Connections:)</td><td id="nb_connections">xx</td></tr>
|
||||
<tr><td style="text-align:right; padding: 4px;">_(Wasted:)</td><td style="padding-right: 20px;" id="total_wasted">0 Kb</td><td style="text-align:right; padding: 4px;">_(Time elapsed:)</td><td style="padding-right: 20px;" id="time_elapsed">xx</td><td></td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend><b>_(Information)</b></legend>
|
||||
<table>
|
||||
<tr><td style="text-align:right; padding: 4px;">_(Save path:)</td><td>xxx</td></tr>
|
||||
<tr><td style="text-align:right; padding: 4px;">_(Created on:)</td><td>xxx</td></tr>
|
||||
<tr><td style="text-align:right; padding: 4px;">_(Torrent hash:)</td><td>xxx</td></tr>
|
||||
<tr><td style="text-align:right; padding: 4px;">_(Save path:)</td><td id="save_path">xxx</td></tr>
|
||||
<tr><td style="text-align:right; padding: 4px;">_(Created on:)</td><td id="creation_date">xxx</td></tr>
|
||||
<tr><td style="text-align:right; padding: 4px;">_(Torrent hash:)</td><td id="torrent_hash">xxx</td></tr>
|
||||
<tr><td style="vertical-align: top; padding: 4px; text-align:right;">
|
||||
<br/>
|
||||
_(Comment:)
|
||||
</td><td>
|
||||
<textarea name="comments" id="comments" rows="15" cols="80">
|
||||
<textarea name="comment" id="comment" rows="15" cols="80">
|
||||
xxx
|
||||
</textarea>
|
||||
</td></tr>
|
||||
</table>
|
||||
<br/>
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
|
||||
<!--
|
||||
static information: save_path, creation_date, torrent_hash, comment
|
||||
|
||||
dynamic information: total_downloaded, total_uploaded, total_wasted, up_limit, dl_limit, time_elapsed, share_ratio, nb_connections
|
||||
|
||||
-->
|
||||
|
||||
<script type="text/javascript">
|
||||
var waiting=false;
|
||||
|
||||
var clearData = function() {
|
||||
$('torrent_hash').set('html', '');
|
||||
$('save_path').set('html', '');
|
||||
$('creation_date').set('html', '');
|
||||
$('comment').set('html', '');
|
||||
$('total_uploaded').set('html', '');
|
||||
$('total_downloaded').set('html', '');
|
||||
$('total_wasted').set('html', '');
|
||||
$('up_limit').set('html', '');
|
||||
$('dl_limit').set('html', '');
|
||||
$('time_elapsed').set('html', '');
|
||||
$('nb_connections').set('html', '');
|
||||
$('share_ratio').set('html', '');
|
||||
}
|
||||
|
||||
var loadData = function() {
|
||||
var current_hash = myTable.getCurrentTorrentHash();
|
||||
if(current_hash == "") {
|
||||
clearData();
|
||||
loadData.delay(2000);
|
||||
return;
|
||||
}
|
||||
// Display hash
|
||||
$('torrent_hash').set('html', current_hash);
|
||||
var url = 'json/propertiesGeneral/'+current_hash;
|
||||
if (!waiting) {
|
||||
waiting=true;
|
||||
var request = new Request.JSON({
|
||||
url: url,
|
||||
method: 'get',
|
||||
onFailure: function() {
|
||||
$('error_div').set('html', 'qBittorrent client is not reachable');
|
||||
waiting=false;
|
||||
loadData.delay(2000);
|
||||
},
|
||||
onSuccess: function(data) {
|
||||
$('error_div').set('html', '');
|
||||
if(data){
|
||||
// Update Torrent data
|
||||
$('save_path').set('html', data.save_path);
|
||||
$('creation_date').set('html', data.creation_date);
|
||||
$('comment').set('html', data.comment);
|
||||
$('total_uploaded').set('html', data.total_uploaded);
|
||||
$('total_downloaded').set('html', data.total_downloaded);
|
||||
$('total_wasted').set('html', data.total_wasted);
|
||||
$('up_limit').set('html', data.up_limit);
|
||||
$('dl_limit').set('html', data.dl_limit);
|
||||
$('time_elapsed').set('html', data.time_elapsed);
|
||||
$('nb_connections').set('html', data.nb_connections);
|
||||
$('share_ratio').set('html', data.share_ratio);
|
||||
} else {
|
||||
clearData();
|
||||
}
|
||||
waiting=false;
|
||||
loadData.delay(2000);
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
|
||||
}
|
||||
// Initial loading
|
||||
loadData();
|
||||
</script>
|
|
@ -160,7 +160,7 @@ window.addEvent('domready', function(){
|
|||
}
|
||||
}
|
||||
waiting=false;
|
||||
ajaxfn.delay(1000);
|
||||
ajaxfn.delay(1500);
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
|
|
|
@ -43,6 +43,13 @@ var dynamicTable = new Class ({
|
|||
this.priority_hidden = false;
|
||||
this.progressIndex = progressIndex;
|
||||
this.filter = 'all';
|
||||
this.current_hash = '';
|
||||
},
|
||||
|
||||
getCurrentTorrentHash: function() {
|
||||
if(this.cur.length > 0)
|
||||
return this.cur[0];
|
||||
return '';
|
||||
},
|
||||
|
||||
altRow: function()
|
||||
|
@ -200,6 +207,7 @@ var dynamicTable = new Class ({
|
|||
temptr.addClass('selected');
|
||||
}
|
||||
this.cur[0] = id;
|
||||
// TODO: Warn Properties panel
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
Loading…
Reference in a new issue