Browse Source

- Web UI: Display generation information in torrent properties

adaptive-webui-19844
Christophe Dumez 15 years ago
parent
commit
e35d100769
  1. 46
      src/eventmanager.cpp
  2. 1
      src/eventmanager.h
  3. 21
      src/httpconnection.cpp
  4. 1
      src/httpconnection.h
  5. 94
      src/json.h
  6. 88
      src/webui/prop-general.html
  7. 2
      src/webui/scripts/client.js
  8. 8
      src/webui/scripts/dynamicTable.js

46
src/eventmanager.cpp

@ -32,6 +32,7 @@
#include "eventmanager.h" #include "eventmanager.h"
#include "bittorrent.h" #include "bittorrent.h"
#include "misc.h" #include "misc.h"
#include "torrentpersistentdata.h"
#include <QDebug> #include <QDebug>
EventManager::EventManager(QObject *parent, Bittorrent *BTSession) EventManager::EventManager(QObject *parent, Bittorrent *BTSession)
@ -43,6 +44,51 @@ QList<QVariantMap> EventManager::getEventList() const {
return event_list.values(); 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) void EventManager::addedTorrent(QTorrentHandle& h)
{ {
modifiedTorrent(h); modifiedTorrent(h);

1
src/eventmanager.h

@ -51,6 +51,7 @@ class EventManager : public QObject
public: public:
EventManager(QObject *parent, Bittorrent* BTSession); EventManager(QObject *parent, Bittorrent* BTSession);
QList<QVariantMap> getEventList() const; QList<QVariantMap> getEventList() const;
QVariantMap getPropGeneralInfo(QString hash) const;
public slots: public slots:
void addedTorrent(QTorrentHandle& h); void addedTorrent(QTorrentHandle& h);

21
src/httpconnection.cpp

@ -147,7 +147,7 @@ void HttpConnection::respond()
} }
if (list.size() == 0) if (list.size() == 0)
list.append("index.html"); list.append("index.html");
if (list.size() == 2) if (list.size() >= 2)
{ {
if (list[0] == "json") if (list[0] == "json")
{ {
@ -156,6 +156,14 @@ void HttpConnection::respond()
respondJson(); respondJson();
return; 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") if (list[0] == "command")
{ {
@ -210,6 +218,17 @@ void HttpConnection::respondJson()
write(); 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) void HttpConnection::respondCommand(QString command)
{ {
if(command == "download") if(command == "download")

1
src/httpconnection.h

@ -56,6 +56,7 @@ class HttpConnection : public QObject
void write(); void write();
virtual void respond(); virtual void respond();
void respondJson(); void respondJson();
void respondGenPropertiesJson(QString hash);
void respondCommand(QString command); void respondCommand(QString command);
void respondNotFound(); void respondNotFound();
void processDownloadedFile(QString, QString); void processDownloadedFile(QString, QString);

94
src/json.h

@ -36,71 +36,79 @@
namespace json { namespace json {
QString toJson(QVariant v) { QString toJson(QVariant v) {
if (v.isNull()) if (v.isNull())
return "null"; return "null";
switch(v.type()) switch(v.type())
{ {
case QVariant::Bool: case QVariant::Bool:
case QVariant::Double: case QVariant::Double:
case QVariant::Int: case QVariant::Int:
case QVariant::LongLong: case QVariant::LongLong:
case QVariant::UInt: case QVariant::UInt:
case QVariant::ULongLong: case QVariant::ULongLong:
return v.value<QString>(); return v.value<QString>();
case QVariant::String: case QVariant::String:
{ {
QString s = v.value<QString>(); QString s = v.value<QString>();
QString result = "\""; QString result = "\"";
for(int i=0; i<s.size(); i++) for(int i=0; i<s.size(); i++)
{ {
QChar ch = s[i]; QChar ch = s[i];
switch(ch.toAscii()) switch(ch.toAscii())
{ {
case '\b': case '\b':
result += "\\b"; result += "\\b";
break; break;
case '\f': case '\f':
result += "\\f"; result += "\\f";
break; break;
case '\n': case '\n':
result += "\\n"; result += "\\n";
break; break;
case '\r': case '\r':
result += "\\r"; result += "\\r";
break; break;
case '\t': case '\t':
result += "\\t"; result += "\\t";
break; break;
case '\"': case '\"':
case '\'': case '\'':
case '\\': case '\\':
case '&': case '&':
result += '\\'; result += '\\';
case '\0': case '\0':
default: default:
result += ch; result += ch;
} }
}
result += "\"";
return result;
}
default:
return "undefined";
} }
result += "\"";
return result;
}
default:
return "undefined";
} }
}
QString toJson(QList<QVariantMap> v) { QString toJson(QVariantMap m) {
QStringList res; QStringList vlist;
foreach(QVariantMap m, v) { foreach(QString key, m.keys()) {
QStringList vlist; vlist << toJson(key)+":"+toJson(m[key]);
foreach(QString key, m.keys()) { }
vlist << toJson(key)+":"+toJson(m[key]); return "{"+vlist.join(",")+"}";
} }
res << "{"+vlist.join(",")+"}";
} QString toJson(QList<QVariantMap> v) {
return "["+res.join(",")+"]"; 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 #endif

88
src/webui/prop-general.html

@ -1,26 +1,100 @@
<fieldset> <fieldset>
<legend><b>_(Transfer)</b></legend> <legend><b>_(Transfer)</b></legend>
<table> <table>
<tr><td style="text-align:right; padding: 4px;">_(Uploaded:)</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>0 Kb</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>0 Kb</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> </table>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend><b>_(Information)</b></legend> <legend><b>_(Information)</b></legend>
<table> <table>
<tr><td style="text-align:right; padding: 4px;">_(Save path:)</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>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>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;"> <tr><td style="vertical-align: top; padding: 4px; text-align:right;">
<br/> <br/>
_(Comment:) _(Comment:)
</td><td> </td><td>
<textarea name="comments" id="comments" rows="15" cols="80"> <textarea name="comment" id="comment" rows="15" cols="80">
xxx xxx
</textarea> </textarea>
</td></tr> </td></tr>
</table> </table>
<br/> <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>

2
src/webui/scripts/client.js

@ -160,7 +160,7 @@ window.addEvent('domready', function(){
} }
} }
waiting=false; waiting=false;
ajaxfn.delay(1000); ajaxfn.delay(1500);
} }
}).send(); }).send();
} }

8
src/webui/scripts/dynamicTable.js

@ -43,6 +43,13 @@ var dynamicTable = new Class ({
this.priority_hidden = false; this.priority_hidden = false;
this.progressIndex = progressIndex; this.progressIndex = progressIndex;
this.filter = 'all'; this.filter = 'all';
this.current_hash = '';
},
getCurrentTorrentHash: function() {
if(this.cur.length > 0)
return this.cur[0];
return '';
}, },
altRow: function() altRow: function()
@ -200,6 +207,7 @@ var dynamicTable = new Class ({
temptr.addClass('selected'); temptr.addClass('selected');
} }
this.cur[0] = id; this.cur[0] = id;
// TODO: Warn Properties panel
} }
} }
return false; return false;

Loading…
Cancel
Save