diff --git a/src/gui/properties/propertieswidget.cpp b/src/gui/properties/propertieswidget.cpp index ea96b0138..aed3b6b12 100644 --- a/src/gui/properties/propertieswidget.cpp +++ b/src/gui/properties/propertieswidget.cpp @@ -365,7 +365,7 @@ void PropertiesWidget::loadDynamicData() { lbl_dllimit->setText(m_torrent->downloadLimit() <= 0 ? QString::fromUtf8(C_INFINITY) : Utils::Misc::friendlyUnit(m_torrent->downloadLimit())+tr("/s", "/second (i.e. per second)")); QString elapsed_txt = Utils::Misc::userFriendlyDuration(m_torrent->activeTime()); if (m_torrent->isSeed()) - elapsed_txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(Utils::Misc::userFriendlyDuration(m_torrent->seedingTime()))+")"; + elapsed_txt += " ("+tr("seeded for %1", "e.g. seeded for 3m10s").arg(Utils::Misc::userFriendlyDuration(m_torrent->seedingTime()))+")"; lbl_elapsed->setText(elapsed_txt); diff --git a/src/gui/transferlistdelegate.cpp b/src/gui/transferlistdelegate.cpp index 0f07ecf25..9ffa5dc15 100644 --- a/src/gui/transferlistdelegate.cpp +++ b/src/gui/transferlistdelegate.cpp @@ -166,7 +166,7 @@ void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem QString txt = Utils::Misc::userFriendlyDuration(index.data().toLongLong()); qlonglong seeding_time = index.data(Qt::UserRole).toLongLong(); if (seeding_time > 0) - txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(Utils::Misc::userFriendlyDuration(seeding_time))+")"; + txt += " ("+tr("seeded for %1", "e.g. seeded for 3m10s").arg(Utils::Misc::userFriendlyDuration(seeding_time))+")"; QItemDelegate::drawDisplay(painter, opt, opt.rect, txt); break; } diff --git a/src/webui/btjson.cpp b/src/webui/btjson.cpp index e3196a133..c6fd94a62 100644 --- a/src/webui/btjson.cpp +++ b/src/webui/btjson.cpp @@ -114,22 +114,39 @@ static const char KEY_TRACKER_PEERS[] = "num_peers"; static const char KEY_WEBSEED_URL[] = "url"; // Torrent keys (Properties) -static const char KEY_PROP_SAVE_PATH[] = "save_path"; -static const char KEY_PROP_CREATION_DATE[] = "creation_date"; -static const char KEY_PROP_PIECE_SIZE[] = "piece_size"; -static const char KEY_PROP_COMMENT[] = "comment"; -static const char KEY_PROP_WASTED[] = "total_wasted"; -static const char KEY_PROP_UPLOADED[] = "total_uploaded"; -static const char KEY_PROP_UPLOADED_SESSION[] = "total_uploaded_session"; -static const char KEY_PROP_DOWNLOADED[] = "total_downloaded"; -static const char KEY_PROP_DOWNLOADED_SESSION[] = "total_downloaded_session"; -static const char KEY_PROP_UP_LIMIT[] = "up_limit"; -static const char KEY_PROP_DL_LIMIT[] = "dl_limit"; static const char KEY_PROP_TIME_ELAPSED[] = "time_elapsed"; static const char KEY_PROP_SEEDING_TIME[] = "seeding_time"; +static const char KEY_PROP_ETA[] = "eta"; static const char KEY_PROP_CONNECT_COUNT[] = "nb_connections"; static const char KEY_PROP_CONNECT_COUNT_LIMIT[] = "nb_connections_limit"; +static const char KEY_PROP_DOWNLOADED[] = "total_downloaded"; +static const char KEY_PROP_DOWNLOADED_SESSION[] = "total_downloaded_session"; +static const char KEY_PROP_UPLOADED[] = "total_uploaded"; +static const char KEY_PROP_UPLOADED_SESSION[] = "total_uploaded_session"; +static const char KEY_PROP_DL_SPEED[] = "dl_speed"; +static const char KEY_PROP_DL_SPEED_AVG[] = "dl_speed_avg"; +static const char KEY_PROP_UP_SPEED[] = "up_speed"; +static const char KEY_PROP_UP_SPEED_AVG[] = "up_speed_avg"; +static const char KEY_PROP_DL_LIMIT[] = "dl_limit"; +static const char KEY_PROP_UP_LIMIT[] = "up_limit"; +static const char KEY_PROP_WASTED[] = "total_wasted"; +static const char KEY_PROP_SEEDS[] = "seeds"; +static const char KEY_PROP_SEEDS_TOTAL[] = "seeds_total"; +static const char KEY_PROP_PEERS[] = "peers"; +static const char KEY_PROP_PEERS_TOTAL[] = "peers_total"; static const char KEY_PROP_RATIO[] = "share_ratio"; +static const char KEY_PROP_REANNOUNCE[] = "reannounce"; +static const char KEY_PROP_TOTAL_SIZE[] = "total_size"; +static const char KEY_PROP_PIECES_NUM[] = "pieces_num"; +static const char KEY_PROP_PIECE_SIZE[] = "piece_size"; +static const char KEY_PROP_PIECES_HAVE[] = "pieces_have"; +static const char KEY_PROP_CREATED_BY[] = "created_by"; +static const char KEY_PROP_LAST_SEEN[] = "last_seen"; +static const char KEY_PROP_ADDITION_DATE[] = "addition_date"; +static const char KEY_PROP_COMPLETION_DATE[] = "completion_date"; +static const char KEY_PROP_CREATION_DATE[] = "creation_date"; +static const char KEY_PROP_SAVE_PATH[] = "save_path"; +static const char KEY_PROP_COMMENT[] = "comment"; // File keys static const char KEY_FILE_NAME[] = "name"; @@ -410,22 +427,39 @@ QByteArray btjson::getWebSeedsForTorrent(const QString& hash) * * The return value is a JSON-formatted dictionary. * The dictionary keys are: - * - "save_path": Torrent save path - * - "creation_date": Torrent creation date - * - "piece_size": Torrent piece size - * - "comment": Torrent comment - * - "total_wasted": Total data wasted for torrent - * - "total_uploaded": Total data uploaded for torrent - * - "total_uploaded_session": Total data uploaded this session - * - "total_downloaded": Total data uploaded for torrent - * - "total_downloaded_session": Total data downloaded this session - * - "up_limit": Torrent upload limit - * - "dl_limit": Torrent download limit * - "time_elapsed": Torrent elapsed time * - "seeding_time": Torrent elapsed time while complete + * - "eta": Torrent ETA * - "nb_connections": Torrent connection count * - "nb_connections_limit": Torrent connection count limit + * - "total_downloaded": Total data uploaded for torrent + * - "total_downloaded_session": Total data downloaded this session + * - "total_uploaded": Total data uploaded for torrent + * - "total_uploaded_session": Total data uploaded this session + * - "dl_speed": Torrent download speed + * - "dl_speed_avg": Torrent average download speed + * - "up_speed": Torrent upload speed + * - "up_speed_avg": Torrent average upload speed + * - "dl_limit": Torrent download limit + * - "up_limit": Torrent upload limit + * - "total_wasted": Total data wasted for torrent + * - "seeds": Torrent connected seeds + * - "seeds_total": Torrent total number of seeds + * - "peers": Torrent connected peers + * - "peers_total": Torrent total number of peers * - "share_ratio": Torrent share ratio + * - "reannounce": Torrent next reannounce time + * - "total_size": Torrent total size + * - "pieces_num": Torrent pieces count + * - "piece_size": Torrent piece size + * - "pieces_have": Torrent pieces have + * - "created_by": Torrent creator + * - "last_seen": Torrent last seen complete + * - "addition_date": Torrent addition date + * - "completion_date": Torrent completion date + * - "creation_date": Torrent creation date + * - "save_path": Torrent save path + * - "comment": Torrent comment */ QByteArray btjson::getPropertiesForTorrent(const QString& hash) { @@ -436,26 +470,47 @@ QByteArray btjson::getPropertiesForTorrent(const QString& hash) return QByteArray(); } - if (!torrent->hasMetadata()) - return QByteArray(); - - dataDict[KEY_PROP_SAVE_PATH] = Utils::Fs::toNativePath(torrent->savePath()); - dataDict[KEY_PROP_CREATION_DATE] = torrent->creationDate().toTime_t(); - dataDict[KEY_PROP_PIECE_SIZE] = torrent->pieceLength(); - dataDict[KEY_PROP_COMMENT] = torrent->comment(); - dataDict[KEY_PROP_WASTED] = torrent->wastedSize(); - dataDict[KEY_PROP_UPLOADED] = torrent->totalUpload(); - dataDict[KEY_PROP_UPLOADED_SESSION] = torrent->totalPayloadUpload(); - dataDict[KEY_PROP_DOWNLOADED] = torrent->totalDownload(); - dataDict[KEY_PROP_DOWNLOADED_SESSION] = torrent->totalPayloadDownload(); - dataDict[KEY_PROP_UP_LIMIT] = torrent->uploadLimit() <= 0 ? -1 : torrent->uploadLimit(); - dataDict[KEY_PROP_DL_LIMIT] = torrent->downloadLimit() <= 0 ? -1 : torrent->downloadLimit(); dataDict[KEY_PROP_TIME_ELAPSED] = torrent->activeTime(); dataDict[KEY_PROP_SEEDING_TIME] = torrent->seedingTime(); + dataDict[KEY_PROP_ETA] = torrent->eta(); dataDict[KEY_PROP_CONNECT_COUNT] = torrent->connectionsCount(); dataDict[KEY_PROP_CONNECT_COUNT_LIMIT] = torrent->connectionsLimit(); + dataDict[KEY_PROP_DOWNLOADED] = torrent->totalDownload(); + dataDict[KEY_PROP_DOWNLOADED_SESSION] = torrent->totalPayloadDownload(); + dataDict[KEY_PROP_UPLOADED] = torrent->totalUpload(); + dataDict[KEY_PROP_UPLOADED_SESSION] = torrent->totalPayloadUpload(); + dataDict[KEY_PROP_DL_SPEED] = torrent->downloadPayloadRate(); + dataDict[KEY_PROP_DL_SPEED_AVG] = torrent->totalDownload() / (1 + torrent->activeTime() - torrent->finishedTime()); + dataDict[KEY_PROP_UP_SPEED] = torrent->uploadPayloadRate(); + dataDict[KEY_PROP_UP_SPEED_AVG] = torrent->totalUpload() / (1 + torrent->activeTime()); + dataDict[KEY_PROP_DL_LIMIT] = torrent->downloadLimit() <= 0 ? -1 : torrent->downloadLimit(); + dataDict[KEY_PROP_UP_LIMIT] = torrent->uploadLimit() <= 0 ? -1 : torrent->uploadLimit(); + dataDict[KEY_PROP_WASTED] = torrent->wastedSize(); + dataDict[KEY_PROP_SEEDS] = torrent->seedsCount(); + dataDict[KEY_PROP_SEEDS_TOTAL] = torrent->totalSeedsCount(); + dataDict[KEY_PROP_PEERS] = torrent->leechsCount(); + dataDict[KEY_PROP_PEERS_TOTAL] = torrent->totalLeechersCount(); const qreal ratio = torrent->realRatio(); dataDict[KEY_PROP_RATIO] = ratio > BitTorrent::TorrentHandle::MAX_RATIO ? -1 : ratio; + dataDict[KEY_PROP_REANNOUNCE] = torrent->nextAnnounce(); + dataDict[KEY_PROP_TOTAL_SIZE] = torrent->totalSize(); + dataDict[KEY_PROP_PIECES_NUM] = torrent->piecesCount(); + dataDict[KEY_PROP_PIECE_SIZE] = torrent->pieceLength(); + dataDict[KEY_PROP_PIECES_HAVE] = torrent->piecesHave(); + dataDict[KEY_PROP_CREATED_BY] = torrent->creator(); + dataDict[KEY_PROP_ADDITION_DATE] = torrent->addedTime().toTime_t(); + if (torrent->hasMetadata()) { + dataDict[KEY_PROP_LAST_SEEN] = torrent->lastSeenComplete().isValid() ? (int)torrent->lastSeenComplete().toTime_t() : -1; + dataDict[KEY_PROP_COMPLETION_DATE] = torrent->completedTime().isValid() ? (int)torrent->completedTime().toTime_t() : -1; + dataDict[KEY_PROP_CREATION_DATE] = torrent->creationDate().toTime_t(); + } + else { + dataDict[KEY_PROP_LAST_SEEN] = -1; + dataDict[KEY_PROP_COMPLETION_DATE] = -1; + dataDict[KEY_PROP_CREATION_DATE] = -1; + } + dataDict[KEY_PROP_SAVE_PATH] = torrent->savePathParsed(); + dataDict[KEY_PROP_COMMENT] = torrent->comment(); return json::toJson(dataDict); } diff --git a/src/webui/www/public/css/style.css b/src/webui/www/public/css/style.css index 25f1fbb0c..9df76aadf 100644 --- a/src/webui/www/public/css/style.css +++ b/src/webui/www/public/css/style.css @@ -358,6 +358,13 @@ ul.filterList li:hover a { color: white; } +td.generalLabel { + white-space: nowrap; + text-align: right; + width: 1px; + vertical-align: top; +} + #filesTable { line-height: 20px; } diff --git a/src/webui/www/public/properties_content.html b/src/webui/www/public/properties_content.html index 520a28045..2e906712a 100644 --- a/src/webui/www/public/properties_content.html +++ b/src/webui/www/public/properties_content.html @@ -1,24 +1,49 @@
QBT_TR(Transfer)QBT_TR - - - - +
QBT_TR(Uploaded:)QBT_TRQBT_TR(UP limit:)QBT_TRQBT_TR(Share ratio:)QBT_TR
QBT_TR(Downloaded:)QBT_TRQBT_TR(DL limit:)QBT_TRQBT_TR(Connections:)QBT_TR
QBT_TR(Wasted:)QBT_TRQBT_TR(Time active:)QBT_TR
+ + + + + + + + + + + + + + + + + + + + +
QBT_TR(Time Active:)QBT_TRQBT_TR(ETA:)QBT_TRQBT_TR(Connections:)QBT_TR
QBT_TR(Downloaded:)QBT_TRQBT_TR(Uploaded:)QBT_TRQBT_TR(Seeds:)QBT_TR
QBT_TR(Download Speed:)QBT_TRQBT_TR(Upload Speed:)QBT_TRQBT_TR(Peers:)QBT_TR
QBT_TR(Download Limit:)QBT_TRQBT_TR(Upload Limit:)QBT_TRQBT_TR(Wasted:)QBT_TR
QBT_TR(Share Ratio:)QBT_TRQBT_TR(Reannounce In:)QBT_TRQBT_TR(Last Seen Complete:)QBT_TR
-
QBT_TR(Information)QBT_TR - - - - - - - +
QBT_TR(Save path:)QBT_TR
QBT_TR(Created on:)QBT_TR
QBT_TR(Piece size:)QBT_TR
QBT_TR(Torrent hash:)QBT_TR
QBT_TR(Comment:)QBT_TR
+ + + + + + + + + + + + + + +
QBT_TR(Total Size:)QBT_TRQBT_TR(Pieces:)QBT_TRQBT_TR(Created By:)QBT_TR
QBT_TR(Added On:)QBT_TRQBT_TR(Completed On:)QBT_TRQBT_TR(Created On:)QBT_TR
QBT_TR(Torrent Hash:)QBT_TR
QBT_TR(Save Path:)QBT_TR
QBT_TR(Comment:)QBT_TR
-
diff --git a/src/webui/www/public/scripts/misc.js b/src/webui/www/public/scripts/misc.js index 645353127..73740cf61 100644 --- a/src/webui/www/public/scripts/misc.js +++ b/src/webui/www/public/scripts/misc.js @@ -12,12 +12,19 @@ function friendlyUnit(value, isSpeed) { if (value < 0) return "QBT_TR(Unknown)QBT_TR"; + var i = 0; - while (value >= 1024. && i++ < 6) + while (value >= 1024. && i < 4) { value /= 1024.; + ++i; + } var ret; - ret = (Math.floor(10 * value) / 10).toFixed(1) //Don't round up + if (i == 0) + ret = value + " " + units[i]; + else + ret = (Math.floor(10 * value) / 10).toFixed(1) //Don't round up + " " + units[i]; + if (isSpeed) ret += "QBT_TR(/s)QBT_TR"; return ret; @@ -75,8 +82,16 @@ if (!Date.prototype.toISOString) { }()); } +/* + * JS counterpart of the function in src/misc.cpp + */ +function parseHtmlLinks(text) { + var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig; + return text.replace(exp,"$1"); +} + function escapeHtml(str) { var div = document.createElement('div'); div.appendChild(document.createTextNode(str)); return div.innerHTML; -}; \ No newline at end of file +}; diff --git a/src/webui/www/public/scripts/prop-general.js b/src/webui/www/public/scripts/prop-general.js index a364b88ec..e7070c8cc 100644 --- a/src/webui/www/public/scripts/prop-general.js +++ b/src/webui/www/public/scripts/prop-general.js @@ -1,17 +1,28 @@ var clearData = function() { + $('time_elapsed').set('html', ''); + $('eta').set('html', ''); + $('nb_connections').set('html', ''); + $('total_downloaded').set('html', ''); + $('total_uploaded').set('html', ''); + $('dl_speed').set('html', ''); + $('up_speed').set('html', ''); + $('dl_limit').set('html', ''); + $('up_limit').set('html', ''); + $('total_wasted').set('html', ''); + $('seeds').set('html', ''); + $('peers').set('html', ''); + $('share_ratio').set('html', ''); + $('reannounce').set('html', ''); + $('last_seen').set('html', ''); + $('total_size').set('html', ''); + $('pieces').set('html', ''); + $('created_by').set('html', ''); + $('addition_date').set('html', ''); + $('completion_date').set('html', ''); + $('creation_date').set('html', ''); $('torrent_hash').set('html', ''); $('save_path').set('html', ''); - $('creation_date').set('html', ''); - $('piece_size').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 loadTorrentDataTimer; @@ -45,31 +56,65 @@ var loadTorrentData = function() { if (data) { var temp; // Update Torrent data - $('save_path').set('html', data.save_path); - temp = data.creation_date; - var timestamp = "QBT_TR(Unknown)QBT_TR"; - if (temp != -1) - timestamp = new Date(data.creation_date * 1000).toISOString(); - $('creation_date').set('html', timestamp); - $('piece_size').set('html', friendlyUnit(data.piece_size)); - $('comment').set('html', data.comment); - $('total_uploaded').set('html', friendlyUnit(data.total_uploaded) + - " (" + friendlyUnit(data.total_uploaded_session) + - " QBT_TR(this session)QBT_TR" + ")"); - $('total_downloaded').set('html', friendlyUnit(data.total_downloaded) + - " (" + friendlyUnit(data.total_downloaded_session) + - " QBT_TR(this session)QBT_TR" + ")"); - $('total_wasted').set('html', friendlyUnit(data.total_wasted)); - temp = data.up_limit; - $('up_limit').set('html', temp == -1 ? "∞" : temp); - temp = data.dl_limit; - $('dl_limit').set('html', temp == -1 ? "∞" : temp); - temp = friendlyDuration(data.time_elapsed) + - " (" + "QBT_TR(Seeded for %1)QBT_TR".replace("%1", friendlyDuration(data.seeding_time)) + ")"; + temp = friendlyDuration(data.time_elapsed) + if (data.seeding_time > 0) + temp += " (" + "QBT_TR(seeded for %1)QBT_TR".replace("%1", friendlyDuration(data.seeding_time)) + ")"; $('time_elapsed').set('html', temp); + $('eta').set('html', friendlyDuration(data.eta)); temp = data.nb_connections + " (" + "QBT_TR(%1 max)QBT_TR".replace("%1", data.nb_connections_limit) + ")"; $('nb_connections').set('html', temp); + temp = friendlyUnit(data.total_downloaded) + + " (" + friendlyUnit(data.total_downloaded_session) + + " QBT_TR(this session)QBT_TR" + ")"; + $('total_downloaded').set('html', temp); + temp = friendlyUnit(data.total_uploaded) + + " (" + friendlyUnit(data.total_uploaded_session) + + " QBT_TR(this session)QBT_TR" + ")"; + $('total_uploaded').set('html', temp); + temp = friendlyUnit(data.dl_speed, true) + " QBT_TR((%1/s avg.))QBT_TR".replace("%1", friendlyUnit(data.dl_speed_avg)); + $('dl_speed').set('html', temp); + temp = friendlyUnit(data.up_speed, true) + " QBT_TR((%1/s avg.))QBT_TR".replace("%1", friendlyUnit(data.up_speed_avg)); + $('up_speed').set('html', temp); + temp = (data.dl_limit == -1 ? "∞" : friendlyUnit(data.dl_limit, true)); + $('dl_limit').set('html', temp); + temp = (data.up_limit == -1 ? "∞" : friendlyUnit(data.up_limit, true)); + $('up_limit').set('html', temp); + $('total_wasted').set('html', friendlyUnit(data.total_wasted)); + temp = data.seeds + " QBT_TR((%1 total))QBT_TR".replace("%1", data.seeds_total); + $('seeds').set('html', temp); + temp = data.peers + " QBT_TR((%1 total))QBT_TR".replace("%1", data.peers_total); + $('peers').set('html', temp); $('share_ratio').set('html', data.share_ratio.toFixed(2)); + $('reannounce').set('html', friendlyDuration(data.reannounce)); + if (data.last_seen != -1) + temp = new Date(data.last_seen * 1000).toLocaleString(); + else + temp = "QBT_TR(Never)QBT_TR"; + $('last_seen').set('html', temp); + $('total_size').set('html', friendlyUnit(data.total_size)); + if (data.pieces_num != -1) + temp = "QBT_TR(%1 x %2 (have %3))QBT_TR".replace("%1", data.pieces_num).replace("%2", friendlyUnit(data.piece_size)).replace("%3", data.pieces_have); + else + temp = "QBT_TR(Unknown)QBT_TR"; + $('pieces').set('html', temp); + $('created_by').set('html', data.created_by); + if (data.addition_date != -1) + temp = new Date(data.addition_date * 1000).toLocaleString(); + else + temp = "QBT_TR(Unknown)QBT_TR"; + $('addition_date').set('html', temp); + if (data.completion_date != -1) + temp = new Date(data.completion_date * 1000).toLocaleString(); + else + temp = ""; + $('completion_date').set('html', temp); + if (data.creation_date != -1) + temp = new Date(data.creation_date * 1000).toLocaleString(); + else + temp = "QBT_TR(Unknown)QBT_TR"; + $('creation_date').set('html', temp); + $('save_path').set('html', data.save_path); + $('comment').set('html', parseHtmlLinks(data.comment)); } else { clearData();