mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-22 20:44:15 +00:00
Merge pull request #2145 from pmzqla/webui
Make Web API locale independent
This commit is contained in:
commit
e8bec885cb
13
src/misc.cpp
13
src/misc.cpp
@ -289,9 +289,8 @@ int misc::pythonVersion() {
|
|||||||
// use Binary prefix standards from IEC 60027-2
|
// use Binary prefix standards from IEC 60027-2
|
||||||
// see http://en.wikipedia.org/wiki/Kilobyte
|
// see http://en.wikipedia.org/wiki/Kilobyte
|
||||||
// value must be given in bytes
|
// value must be given in bytes
|
||||||
// FIXME: Remove the 'webui' variable, when the webui API is reworked
|
|
||||||
// to send numbers instead of strings with suffixes
|
// to send numbers instead of strings with suffixes
|
||||||
QString misc::friendlyUnit(qreal val, bool is_speed, bool webui) {
|
QString misc::friendlyUnit(qreal val, bool is_speed) {
|
||||||
if (val < 0)
|
if (val < 0)
|
||||||
return QCoreApplication::translate("misc", "Unknown", "Unknown (size)");
|
return QCoreApplication::translate("misc", "Unknown", "Unknown (size)");
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -301,7 +300,7 @@ QString misc::friendlyUnit(qreal val, bool is_speed, bool webui) {
|
|||||||
if (i == 0)
|
if (i == 0)
|
||||||
ret = QString::number((long)val) + " " + QCoreApplication::translate("misc", units[0].source, units[0].comment);
|
ret = QString::number((long)val) + " " + QCoreApplication::translate("misc", units[0].source, units[0].comment);
|
||||||
else
|
else
|
||||||
ret = accurateDoubleToString(val, 1, !webui) + " " + QCoreApplication::translate("misc", units[i].source, units[i].comment);
|
ret = accurateDoubleToString(val, 1) + " " + QCoreApplication::translate("misc", units[i].source, units[i].comment);
|
||||||
if (is_speed)
|
if (is_speed)
|
||||||
ret += QCoreApplication::translate("misc", "/s", "per second");
|
ret += QCoreApplication::translate("misc", "/s", "per second");
|
||||||
return ret;
|
return ret;
|
||||||
@ -630,9 +629,8 @@ bool misc::naturalSort(QString left, QString right, bool &result) { // uses less
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// FIXME: Remove the 'localized' variable, when the webui API is reworked
|
|
||||||
// to send numbers instead of strings with suffixes
|
// to send numbers instead of strings with suffixes
|
||||||
QString misc::accurateDoubleToString(const double &n, const int &precision, bool localized) {
|
QString misc::accurateDoubleToString(const double &n, const int &precision) {
|
||||||
/* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9
|
/* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9
|
||||||
** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 The problem manifests when
|
** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 The problem manifests when
|
||||||
** the number has more digits after the decimal than we want AND the digit after
|
** the number has more digits after the decimal than we want AND the digit after
|
||||||
@ -640,10 +638,7 @@ QString misc::accurateDoubleToString(const double &n, const int &precision, bool
|
|||||||
** precision we add an extra 0 behind 1 in the below algorithm. */
|
** precision we add an extra 0 behind 1 in the below algorithm. */
|
||||||
|
|
||||||
double prec = std::pow(10.0, precision);
|
double prec = std::pow(10.0, precision);
|
||||||
if (localized)
|
return QLocale::system().toString(std::floor(n*prec)/prec, 'f', precision);
|
||||||
return QLocale::system().toString(std::floor(n*prec)/prec, 'f', precision);
|
|
||||||
else
|
|
||||||
return QString::number(std::floor(n*prec)/prec, 'f', precision);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements constant-time comparison to protect against timing attacks
|
// Implements constant-time comparison to protect against timing attacks
|
||||||
|
@ -83,7 +83,7 @@ namespace misc
|
|||||||
// use Binary prefix standards from IEC 60027-2
|
// use Binary prefix standards from IEC 60027-2
|
||||||
// see http://en.wikipedia.org/wiki/Kilobyte
|
// see http://en.wikipedia.org/wiki/Kilobyte
|
||||||
// value must be given in bytes
|
// value must be given in bytes
|
||||||
QString friendlyUnit(qreal val, bool is_speed = false, bool webui=false);
|
QString friendlyUnit(qreal val, bool is_speed = false);
|
||||||
bool isPreviewable(const QString& extension);
|
bool isPreviewable(const QString& extension);
|
||||||
QString magnetUriToName(const QString& magnet_uri);
|
QString magnetUriToName(const QString& magnet_uri);
|
||||||
QString magnetUriToHash(const QString& magnet_uri);
|
QString magnetUriToHash(const QString& magnet_uri);
|
||||||
@ -100,7 +100,7 @@ namespace misc
|
|||||||
QList<bool> boolListfromStringList(const QStringList &l);
|
QList<bool> boolListfromStringList(const QStringList &l);
|
||||||
|
|
||||||
QString toQString(time_t t);
|
QString toQString(time_t t);
|
||||||
QString accurateDoubleToString(const double &n, const int &precision, bool localized=true);
|
QString accurateDoubleToString(const double &n, const int &precision);
|
||||||
|
|
||||||
#ifndef DISABLE_GUI
|
#ifndef DISABLE_GUI
|
||||||
bool naturalSort(QString left, QString right, bool& result);
|
bool naturalSort(QString left, QString right, bool& result);
|
||||||
|
@ -103,6 +103,15 @@ QString QTorrentHandle::creation_date() const {
|
|||||||
return t ? misc::toQString(*t) : "";
|
return t ? misc::toQString(*t) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qlonglong QTorrentHandle::creation_date_unix() const {
|
||||||
|
#if LIBTORRENT_VERSION_NUM < 10000
|
||||||
|
boost::optional<time_t> t = torrent_handle::get_torrent_info().creation_date();
|
||||||
|
#else
|
||||||
|
boost::optional<time_t> t = torrent_handle::torrent_file()->creation_date();
|
||||||
|
#endif
|
||||||
|
return t ? *t : -1;
|
||||||
|
}
|
||||||
|
|
||||||
QString QTorrentHandle::current_tracker() const {
|
QString QTorrentHandle::current_tracker() const {
|
||||||
return misc::toQString(status(0x0).current_tracker);
|
return misc::toQString(status(0x0).current_tracker);
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,7 @@ public:
|
|||||||
bool is_checking() const;
|
bool is_checking() const;
|
||||||
bool is_sequential_download() const;
|
bool is_sequential_download() const;
|
||||||
QString creation_date() const;
|
QString creation_date() const;
|
||||||
|
qlonglong creation_date_unix() const;
|
||||||
bool priv() const;
|
bool priv() const;
|
||||||
bool first_last_piece_first() const;
|
bool first_last_piece_first() const;
|
||||||
QString root_path() const;
|
QString root_path() const;
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "btjson.h"
|
#include "btjson.h"
|
||||||
#include "misc.h"
|
|
||||||
#include "fs_utils.h"
|
#include "fs_utils.h"
|
||||||
#include "qbtsession.h"
|
#include "qbtsession.h"
|
||||||
#include "torrentpersistentdata.h"
|
#include "torrentpersistentdata.h"
|
||||||
@ -89,7 +88,9 @@ static const char KEY_TORRENT_DLSPEED[] = "dlspeed";
|
|||||||
static const char KEY_TORRENT_UPSPEED[] = "upspeed";
|
static const char KEY_TORRENT_UPSPEED[] = "upspeed";
|
||||||
static const char KEY_TORRENT_PRIORITY[] = "priority";
|
static const char KEY_TORRENT_PRIORITY[] = "priority";
|
||||||
static const char KEY_TORRENT_SEEDS[] = "num_seeds";
|
static const char KEY_TORRENT_SEEDS[] = "num_seeds";
|
||||||
|
static const char KEY_TORRENT_NUM_COMPLETE[] = "num_complete";
|
||||||
static const char KEY_TORRENT_LEECHS[] = "num_leechs";
|
static const char KEY_TORRENT_LEECHS[] = "num_leechs";
|
||||||
|
static const char KEY_TORRENT_NUM_INCOMPLETE[] = "num_incomplete";
|
||||||
static const char KEY_TORRENT_RATIO[] = "ratio";
|
static const char KEY_TORRENT_RATIO[] = "ratio";
|
||||||
static const char KEY_TORRENT_ETA[] = "eta";
|
static const char KEY_TORRENT_ETA[] = "eta";
|
||||||
static const char KEY_TORRENT_STATE[] = "state";
|
static const char KEY_TORRENT_STATE[] = "state";
|
||||||
@ -107,11 +108,15 @@ static const char KEY_PROP_PIECE_SIZE[] = "piece_size";
|
|||||||
static const char KEY_PROP_COMMENT[] = "comment";
|
static const char KEY_PROP_COMMENT[] = "comment";
|
||||||
static const char KEY_PROP_WASTED[] = "total_wasted";
|
static const char KEY_PROP_WASTED[] = "total_wasted";
|
||||||
static const char KEY_PROP_UPLOADED[] = "total_uploaded";
|
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[] = "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_UP_LIMIT[] = "up_limit";
|
||||||
static const char KEY_PROP_DL_LIMIT[] = "dl_limit";
|
static const char KEY_PROP_DL_LIMIT[] = "dl_limit";
|
||||||
static const char KEY_PROP_TIME_ELAPSED[] = "time_elapsed";
|
static const char KEY_PROP_TIME_ELAPSED[] = "time_elapsed";
|
||||||
|
static const char KEY_PROP_SEEDING_TIME[] = "seeding_time";
|
||||||
static const char KEY_PROP_CONNECT_COUNT[] = "nb_connections";
|
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_RATIO[] = "share_ratio";
|
static const char KEY_PROP_RATIO[] = "share_ratio";
|
||||||
|
|
||||||
// File keys
|
// File keys
|
||||||
@ -122,8 +127,10 @@ static const char KEY_FILE_PRIORITY[] = "priority";
|
|||||||
static const char KEY_FILE_IS_SEED[] = "is_seed";
|
static const char KEY_FILE_IS_SEED[] = "is_seed";
|
||||||
|
|
||||||
// TransferInfo keys
|
// TransferInfo keys
|
||||||
static const char KEY_TRANSFER_DLSPEED[] = "dl_info";
|
static const char KEY_TRANSFER_DLSPEED[] = "dl_info_speed";
|
||||||
static const char KEY_TRANSFER_UPSPEED[] = "up_info";
|
static const char KEY_TRANSFER_DLDATA[] = "dl_info_data";
|
||||||
|
static const char KEY_TRANSFER_UPSPEED[] = "up_info_speed";
|
||||||
|
static const char KEY_TRANSFER_UPDATA[] = "up_info_data";
|
||||||
|
|
||||||
static QVariantMap toMap(const QTorrentHandle& h)
|
static QVariantMap toMap(const QTorrentHandle& h)
|
||||||
{
|
{
|
||||||
@ -132,25 +139,21 @@ static QVariantMap toMap(const QTorrentHandle& h)
|
|||||||
QVariantMap ret;
|
QVariantMap ret;
|
||||||
ret[KEY_TORRENT_HASH] = h.hash();
|
ret[KEY_TORRENT_HASH] = h.hash();
|
||||||
ret[KEY_TORRENT_NAME] = h.name();
|
ret[KEY_TORRENT_NAME] = h.name();
|
||||||
ret[KEY_TORRENT_SIZE] = misc::friendlyUnit(status.total_wanted, false, true); // FIXME: Should pass as Number, not formatted String (for sorting).
|
ret[KEY_TORRENT_SIZE] = static_cast<qlonglong>(status.total_wanted);
|
||||||
ret[KEY_TORRENT_PROGRESS] = (double)h.progress(status);
|
ret[KEY_TORRENT_PROGRESS] = h.progress(status);
|
||||||
ret[KEY_TORRENT_DLSPEED] = misc::friendlyUnit(status.download_payload_rate, true, true); // FIXME: Should be passed as a Number
|
ret[KEY_TORRENT_DLSPEED] = status.download_payload_rate;
|
||||||
ret[KEY_TORRENT_UPSPEED] = misc::friendlyUnit(status.upload_payload_rate, true, true); // FIXME: Should be passed as a Number
|
ret[KEY_TORRENT_UPSPEED] = status.upload_payload_rate;
|
||||||
if (QBtSession::instance()->isQueueingEnabled() && h.queue_position(status) >= 0)
|
if (QBtSession::instance()->isQueueingEnabled() && h.queue_position(status) >= 0)
|
||||||
ret[KEY_TORRENT_PRIORITY] = QString::number(h.queue_position(status));
|
ret[KEY_TORRENT_PRIORITY] = h.queue_position(status);
|
||||||
else
|
else
|
||||||
ret[KEY_TORRENT_PRIORITY] = "*";
|
ret[KEY_TORRENT_PRIORITY] = -1;
|
||||||
QString seeds = QString::number(status.num_seeds);
|
ret[KEY_TORRENT_SEEDS] = status.num_seeds;
|
||||||
if (status.num_complete > 0)
|
ret[KEY_TORRENT_NUM_COMPLETE] = status.num_complete;
|
||||||
seeds += " ("+QString::number(status.num_complete)+")";
|
ret[KEY_TORRENT_LEECHS] = status.num_peers - status.num_seeds;
|
||||||
ret[KEY_TORRENT_SEEDS] = seeds;
|
ret[KEY_TORRENT_NUM_INCOMPLETE] = status.num_incomplete;
|
||||||
QString leechs = QString::number(status.num_peers - status.num_seeds);
|
|
||||||
if (status.num_incomplete > 0)
|
|
||||||
leechs += " ("+QString::number(status.num_incomplete)+")";
|
|
||||||
ret[KEY_TORRENT_LEECHS] = leechs;
|
|
||||||
const qreal ratio = QBtSession::instance()->getRealRatio(status);
|
const qreal ratio = QBtSession::instance()->getRealRatio(status);
|
||||||
ret[KEY_TORRENT_RATIO] = (ratio > 100.) ? QString::fromUtf8("∞") : misc::accurateDoubleToString(ratio, 1, false);
|
ret[KEY_TORRENT_RATIO] = (ratio > 100.) ? -1 : ratio;
|
||||||
QString eta;
|
qulonglong eta = 0;
|
||||||
QString state;
|
QString state;
|
||||||
if (h.is_paused(status)) {
|
if (h.is_paused(status)) {
|
||||||
if (h.has_error(status))
|
if (h.has_error(status))
|
||||||
@ -175,14 +178,14 @@ static QVariantMap toMap(const QTorrentHandle& h)
|
|||||||
case torrent_status::downloading:
|
case torrent_status::downloading:
|
||||||
case torrent_status::downloading_metadata:
|
case torrent_status::downloading_metadata:
|
||||||
state = status.download_payload_rate > 0 ? "downloading" : "stalledDL";
|
state = status.download_payload_rate > 0 ? "downloading" : "stalledDL";
|
||||||
eta = misc::userFriendlyDuration(QBtSession::instance()->getETA(h.hash(), status));
|
eta = QBtSession::instance()->getETA(h.hash(), status);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
qWarning("Unrecognized torrent status, should not happen!!! status was %d", h.state());
|
qWarning("Unrecognized torrent status, should not happen!!! status was %d", h.state());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret[KEY_TORRENT_ETA] = eta.isEmpty() ? QString::fromUtf8("∞") : eta;
|
ret[KEY_TORRENT_ETA] = eta ? eta : MAX_ETA;
|
||||||
ret[KEY_TORRENT_STATE] = state;
|
ret[KEY_TORRENT_STATE] = state;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -199,9 +202,11 @@ static QVariantMap toMap(const QTorrentHandle& h)
|
|||||||
* - "progress: Torrent progress
|
* - "progress: Torrent progress
|
||||||
* - "dlspeed": Torrent download speed
|
* - "dlspeed": Torrent download speed
|
||||||
* - "upspeed": Torrent upload speed
|
* - "upspeed": Torrent upload speed
|
||||||
* - "priority": Torrent priority ('*' if queuing is disabled)
|
* - "priority": Torrent priority (-1 if queuing is disabled)
|
||||||
* - "num_seeds": Torrent seed count
|
* - "num_seeds": Torrent seeds connected to
|
||||||
* - "num_leechs": Torrent leecher count
|
* - "num_complete": Torrent seeds in the swarm
|
||||||
|
* - "num_leechs": Torrent leechers connected to
|
||||||
|
* - "num_incomplete": Torrent leechers in the swarm
|
||||||
* - "ratio": Torrent share ratio
|
* - "ratio": Torrent share ratio
|
||||||
* - "eta": Torrent ETA
|
* - "eta": Torrent ETA
|
||||||
* - "state": Torrent state
|
* - "state": Torrent state
|
||||||
@ -252,7 +257,7 @@ QByteArray btjson::getTrackersForTorrent(const QString& hash)
|
|||||||
status = it->fails > 0 ? tr("Not working") : tr("Not contacted yet");
|
status = it->fails > 0 ? tr("Not working") : tr("Not contacted yet");
|
||||||
}
|
}
|
||||||
tracker_dict[KEY_TRACKER_STATUS] = status;
|
tracker_dict[KEY_TRACKER_STATUS] = status;
|
||||||
tracker_dict[KEY_TRACKER_PEERS] = QString::number(trackers_data.value(tracker_url, TrackerInfos(tracker_url)).num_peers);
|
tracker_dict[KEY_TRACKER_PEERS] = static_cast<qulonglong>(trackers_data.value(tracker_url, TrackerInfos(tracker_url)).num_peers);
|
||||||
tracker_dict[KEY_TRACKER_MSG] = data.last_message.trimmed();
|
tracker_dict[KEY_TRACKER_MSG] = data.last_message.trimmed();
|
||||||
|
|
||||||
tracker_list.append(tracker_dict);
|
tracker_list.append(tracker_dict);
|
||||||
@ -276,11 +281,15 @@ QByteArray btjson::getTrackersForTorrent(const QString& hash)
|
|||||||
* - "comment": Torrent comment
|
* - "comment": Torrent comment
|
||||||
* - "total_wasted": Total data wasted for torrent
|
* - "total_wasted": Total data wasted for torrent
|
||||||
* - "total_uploaded": Total data uploaded 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": Total data uploaded for torrent
|
||||||
|
* - "total_downloaded_session": Total data downloaded this session
|
||||||
* - "up_limit": Torrent upload limit
|
* - "up_limit": Torrent upload limit
|
||||||
* - "dl_limit": Torrent download limit
|
* - "dl_limit": Torrent download limit
|
||||||
* - "time_elapsed": Torrent elapsed time
|
* - "time_elapsed": Torrent elapsed time
|
||||||
|
* - "seeding_time": Torrent elapsed time while complete
|
||||||
* - "nb_connections": Torrent connection count
|
* - "nb_connections": Torrent connection count
|
||||||
|
* - "nb_connections_limit": Torrent connection count limit
|
||||||
* - "share_ratio": Torrent share ratio
|
* - "share_ratio": Torrent share ratio
|
||||||
*/
|
*/
|
||||||
QByteArray btjson::getPropertiesForTorrent(const QString& hash)
|
QByteArray btjson::getPropertiesForTorrent(const QString& hash)
|
||||||
@ -298,21 +307,22 @@ QByteArray btjson::getPropertiesForTorrent(const QString& hash)
|
|||||||
if (save_path.isEmpty())
|
if (save_path.isEmpty())
|
||||||
save_path = fsutils::toNativePath(h.save_path());
|
save_path = fsutils::toNativePath(h.save_path());
|
||||||
data[KEY_PROP_SAVE_PATH] = save_path;
|
data[KEY_PROP_SAVE_PATH] = save_path;
|
||||||
data[KEY_PROP_CREATION_DATE] = h.creation_date();
|
data[KEY_PROP_CREATION_DATE] = h.creation_date_unix();
|
||||||
data[KEY_PROP_PIECE_SIZE] = misc::friendlyUnit(h.piece_length(), false, true);
|
data[KEY_PROP_PIECE_SIZE] = static_cast<qlonglong>(h.piece_length());
|
||||||
data[KEY_PROP_COMMENT] = h.comment();
|
data[KEY_PROP_COMMENT] = h.comment();
|
||||||
data[KEY_PROP_WASTED] = misc::friendlyUnit(status.total_failed_bytes + status.total_redundant_bytes, false, true);
|
data[KEY_PROP_WASTED] = static_cast<qlonglong>(status.total_failed_bytes + status.total_redundant_bytes);
|
||||||
data[KEY_PROP_UPLOADED] = QString(misc::friendlyUnit(status.all_time_upload, false, true) + " (" + misc::friendlyUnit(status.total_payload_upload, false, true) + " " + tr("this session") + ")");
|
data[KEY_PROP_UPLOADED] = static_cast<qlonglong>(status.all_time_upload);
|
||||||
data[KEY_PROP_DOWNLOADED] = QString(misc::friendlyUnit(status.all_time_download, false, true) + " (" + misc::friendlyUnit(status.total_payload_download, false, true) + " " + tr("this session") + ")");
|
data[KEY_PROP_UPLOADED_SESSION] = static_cast<qlonglong>(status.total_payload_upload);
|
||||||
data[KEY_PROP_UP_LIMIT] = h.upload_limit() <= 0 ? QString::fromUtf8("∞") : misc::friendlyUnit(h.upload_limit(), true, true);
|
data[KEY_PROP_DOWNLOADED] = static_cast<qlonglong>(status.all_time_download);
|
||||||
data[KEY_PROP_DL_LIMIT] = h.download_limit() <= 0 ? QString::fromUtf8("∞") : misc::friendlyUnit(h.download_limit(), true, true);
|
data[KEY_PROP_DOWNLOADED_SESSION] = static_cast<qlonglong>(status.total_payload_download);
|
||||||
QString elapsed_txt = misc::userFriendlyDuration(status.active_time);
|
data[KEY_PROP_UP_LIMIT] = h.upload_limit() <= 0 ? -1 : h.upload_limit();
|
||||||
if (h.is_seed(status))
|
data[KEY_PROP_DL_LIMIT] = h.download_limit() <= 0 ? -1 : h.download_limit();
|
||||||
elapsed_txt += " ("+tr("Seeded for %1", "e.g. Seeded for 3m10s").arg(misc::userFriendlyDuration(status.seeding_time))+")";
|
data[KEY_PROP_TIME_ELAPSED] = status.active_time;
|
||||||
data[KEY_PROP_TIME_ELAPSED] = elapsed_txt;
|
data[KEY_PROP_SEEDING_TIME] = status.seeding_time;
|
||||||
data[KEY_PROP_CONNECT_COUNT] = QString(QString::number(status.num_connections) + " (" + tr("%1 max", "e.g. 10 max").arg(QString::number(status.connections_limit)) + ")");
|
data[KEY_PROP_CONNECT_COUNT] = status.num_connections;
|
||||||
|
data[KEY_PROP_CONNECT_COUNT_LIMIT] = status.connections_limit;
|
||||||
const qreal ratio = QBtSession::instance()->getRealRatio(status);
|
const qreal ratio = QBtSession::instance()->getRealRatio(status);
|
||||||
data[KEY_PROP_RATIO] = ratio > 100. ? QString::fromUtf8("∞") : misc::accurateDoubleToString(ratio, 1, false);
|
data[KEY_PROP_RATIO] = ratio > 100. ? -1 : ratio;
|
||||||
} catch(const std::exception& e) {
|
} catch(const std::exception& e) {
|
||||||
qWarning() << Q_FUNC_INFO << "Invalid torrent: " << misc::toQStringU(e.what());
|
qWarning() << Q_FUNC_INFO << "Invalid torrent: " << misc::toQStringU(e.what());
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
@ -350,7 +360,7 @@ QByteArray btjson::getFilesForTorrent(const QString& hash)
|
|||||||
fileName.chop(4);
|
fileName.chop(4);
|
||||||
file_dict[KEY_FILE_NAME] = fsutils::toNativePath(fileName);
|
file_dict[KEY_FILE_NAME] = fsutils::toNativePath(fileName);
|
||||||
const size_type size = h.filesize_at(i);
|
const size_type size = h.filesize_at(i);
|
||||||
file_dict[KEY_FILE_SIZE] = misc::friendlyUnit(size, false, true);
|
file_dict[KEY_FILE_SIZE] = static_cast<qlonglong>(size);
|
||||||
file_dict[KEY_FILE_PROGRESS] = (size > 0) ? (fp[i] / (double) size) : 1.;
|
file_dict[KEY_FILE_PROGRESS] = (size > 0) ? (fp[i] / (double) size) : 1.;
|
||||||
file_dict[KEY_FILE_PRIORITY] = priorities[i];
|
file_dict[KEY_FILE_PRIORITY] = priorities[i];
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
@ -371,14 +381,18 @@ QByteArray btjson::getFilesForTorrent(const QString& hash)
|
|||||||
*
|
*
|
||||||
* The return value is a JSON-formatted dictionary.
|
* The return value is a JSON-formatted dictionary.
|
||||||
* The dictionary keys are:
|
* The dictionary keys are:
|
||||||
* - "dl_info": Global download info
|
* - "dl_info_speed": Global download rate
|
||||||
* - "up_info": Global upload info
|
* - "dl_info_data": Data downloaded this session
|
||||||
|
* - "up_info_speed": Global upload rate
|
||||||
|
* - "up_info_data": Data uploaded this session
|
||||||
*/
|
*/
|
||||||
QByteArray btjson::getTransferInfo()
|
QByteArray btjson::getTransferInfo()
|
||||||
{
|
{
|
||||||
CACHED_VARIABLE(QVariantMap, info, CACHE_DURATION_MS);
|
CACHED_VARIABLE(QVariantMap, info, CACHE_DURATION_MS);
|
||||||
session_status sessionStatus = QBtSession::instance()->getSessionStatus();
|
session_status sessionStatus = QBtSession::instance()->getSessionStatus();
|
||||||
info[KEY_TRANSFER_DLSPEED] = tr("D: %1/s - T: %2", "Download speed: x KiB/s - Transferred: x MiB").arg(misc::friendlyUnit(sessionStatus.payload_download_rate, true, true)).arg(misc::friendlyUnit(sessionStatus.total_payload_download, false, true));
|
info[KEY_TRANSFER_DLSPEED] = sessionStatus.payload_download_rate;
|
||||||
info[KEY_TRANSFER_UPSPEED] = tr("U: %1/s - T: %2", "Upload speed: x KiB/s - Transferred: x MiB").arg(misc::friendlyUnit(sessionStatus.payload_upload_rate, true, true)).arg(misc::friendlyUnit(sessionStatus.total_payload_upload, false, true));
|
info[KEY_TRANSFER_DLDATA] = static_cast<qlonglong>(sessionStatus.total_payload_download);
|
||||||
|
info[KEY_TRANSFER_UPSPEED] = sessionStatus.payload_upload_rate;
|
||||||
|
info[KEY_TRANSFER_UPDATA] = static_cast<qlonglong>(sessionStatus.total_payload_upload);
|
||||||
return json::toJson(info);
|
return json::toJson(info);
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
<file>www/public/scripts/download.js</file>
|
<file>www/public/scripts/download.js</file>
|
||||||
<file>www/public/scripts/dynamicTable.js</file>
|
<file>www/public/scripts/dynamicTable.js</file>
|
||||||
<file>www/public/scripts/excanvas-compressed.js</file>
|
<file>www/public/scripts/excanvas-compressed.js</file>
|
||||||
|
<file>www/public/scripts/misc.js</file>
|
||||||
<file>www/public/scripts/mocha.js</file>
|
<file>www/public/scripts/mocha.js</file>
|
||||||
<file>www/public/scripts/mocha-init.js</file>
|
<file>www/public/scripts/mocha-init.js</file>
|
||||||
<file>www/public/scripts/mocha-yc.js</file>
|
<file>www/public/scripts/mocha-yc.js</file>
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
<![endif]-->
|
<![endif]-->
|
||||||
<script type="text/javascript" src="scripts/mocha-yc.js"></script>
|
<script type="text/javascript" src="scripts/mocha-yc.js"></script>
|
||||||
<script type="text/javascript" src="scripts/mocha-init.js"></script>
|
<script type="text/javascript" src="scripts/mocha-init.js"></script>
|
||||||
|
<script type="text/javascript" src="scripts/misc.js"></script>
|
||||||
<script type="text/javascript" src="scripts/progressbar.js"></script>
|
<script type="text/javascript" src="scripts/progressbar.js"></script>
|
||||||
<script type="text/javascript" src="scripts/dynamicTable.js" charset="utf-8"></script>
|
<script type="text/javascript" src="scripts/dynamicTable.js" charset="utf-8"></script>
|
||||||
<script type="text/javascript" src="scripts/client.js" charset="utf-8"></script>
|
<script type="text/javascript" src="scripts/client.js" charset="utf-8"></script>
|
||||||
|
@ -303,7 +303,7 @@ var createPriorityCombo = function(id, selected_prio) {
|
|||||||
row.length = 4;
|
row.length = 4;
|
||||||
row[0] = file.priority;
|
row[0] = file.priority;
|
||||||
row[1] = file.name;
|
row[1] = file.name;
|
||||||
row[2] = file.size;
|
row[2] = friendlyUnit(file.size, false);
|
||||||
row[3] = (file.progress*100).round(1);
|
row[3] = (file.progress*100).round(1);
|
||||||
if(row[3] == 100.0 && file.progress < 1.0)
|
if(row[3] == 100.0 && file.progress < 1.0)
|
||||||
row[3] = 99.9
|
row[3] = 99.9
|
||||||
|
@ -80,19 +80,34 @@ dynamic information: total_downloaded, total_uploaded, total_wasted, up_limit, d
|
|||||||
onSuccess: function(data) {
|
onSuccess: function(data) {
|
||||||
$('error_div').set('html', '');
|
$('error_div').set('html', '');
|
||||||
if(data){
|
if(data){
|
||||||
|
var temp;
|
||||||
// Update Torrent data
|
// Update Torrent data
|
||||||
$('save_path').set('html', data.save_path);
|
$('save_path').set('html', data.save_path);
|
||||||
$('creation_date').set('html', data.creation_date);
|
temp = data.creation_date;
|
||||||
$('piece_size').set('html', data.piece_size);
|
var timestamp = "_(Unknown)";
|
||||||
|
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);
|
$('comment').set('html', data.comment);
|
||||||
$('total_uploaded').set('html', data.total_uploaded);
|
$('total_uploaded').set('html', friendlyUnit(data.total_uploaded) +
|
||||||
$('total_downloaded').set('html', data.total_downloaded);
|
" (" + friendlyUnit(data.total_uploaded_session) +
|
||||||
|
" (" + "_(this session)" + ")");
|
||||||
|
$('total_downloaded').set('html', friendlyUnit(data.total_downloaded) +
|
||||||
|
" (" + friendlyUnit(data.total_downloaded_session) +
|
||||||
|
" (" + "_(this session)" + ")");
|
||||||
$('total_wasted').set('html', data.total_wasted);
|
$('total_wasted').set('html', data.total_wasted);
|
||||||
$('up_limit').set('html', data.up_limit);
|
temp = data.up_limit;
|
||||||
$('dl_limit').set('html', data.dl_limit);
|
$('up_limit').set('html', temp == -1 ? "∞" : temp);
|
||||||
$('time_elapsed').set('html', data.time_elapsed);
|
temp = data.dl_limit;
|
||||||
$('nb_connections').set('html', data.nb_connections);
|
$('dl_limit').set('html', temp == -1 ? "∞" : temp);
|
||||||
$('share_ratio').set('html', data.share_ratio);
|
temp = friendlyDuration(status.active_time);
|
||||||
|
if (status.is_seed)
|
||||||
|
temp += " (" + "_(Seeded for %1)".replace("%1", status.seeding_time) + ")";
|
||||||
|
$('time_elapsed').set('html', temp);
|
||||||
|
temp = data.nb_connections + " (" + "_(%1 max)".replace("%1", status.nb_connections_limit) + ")";
|
||||||
|
$('nb_connections').set('html', temp);
|
||||||
|
$('share_ratio').set('html', data.share_ratio.toFixed(2));
|
||||||
} else {
|
} else {
|
||||||
clearData();
|
clearData();
|
||||||
}
|
}
|
||||||
|
@ -108,8 +108,10 @@ window.addEvent('load', function(){
|
|||||||
},
|
},
|
||||||
onSuccess: function(info) {
|
onSuccess: function(info) {
|
||||||
if(info) {
|
if(info) {
|
||||||
$("DlInfos").set('html', info.dl_info);
|
$("DlInfos").set('html', "_(D: %1 - T: %2)".replace("%1", friendlyUnit(info.dl_info_speed, true))
|
||||||
$("UpInfos").set('html', info.up_info);
|
.replace("%2", friendlyUnit(info.dl_info_data, false)));
|
||||||
|
$("UpInfos").set('html', "_(U: %1 - T: %2)".replace("%1", friendlyUnit(info.up_info_speed, true))
|
||||||
|
.replace("%2", friendlyUnit(info.up_info_data, false)));
|
||||||
waitingTrInfo=false;
|
waitingTrInfo=false;
|
||||||
loadTransferInfo.delay(3000);
|
loadTransferInfo.delay(3000);
|
||||||
}
|
}
|
||||||
@ -143,30 +145,47 @@ window.addEvent('load', function(){
|
|||||||
events.each(function(event){
|
events.each(function(event){
|
||||||
events_hashes[events_hashes.length] = event.hash;
|
events_hashes[events_hashes.length] = event.hash;
|
||||||
var row = new Array();
|
var row = new Array();
|
||||||
|
var data = new Array();
|
||||||
row.length = 10;
|
row.length = 10;
|
||||||
row[0] = stateToImg(event.state);
|
row[0] = stateToImg(event.state);
|
||||||
row[1] = event.name;
|
row[1] = event.name;
|
||||||
row[2] = event.priority
|
row[2] = event.priority > -1 ? event.priority : null;
|
||||||
row[3] = event.size;
|
data[2] = event.priority;
|
||||||
|
row[3] = friendlyUnit(event.size, false);
|
||||||
|
data[3] = event.size;
|
||||||
row[4] = (event.progress*100).round(1);
|
row[4] = (event.progress*100).round(1);
|
||||||
if(row[4] == 100.0 && event.progress != 1.0)
|
if(row[4] == 100.0 && event.progress != 1.0)
|
||||||
row[4] = 99.9;
|
row[4] = 99.9;
|
||||||
row[5] = event.num_seeds;
|
data[4] = event.progress;
|
||||||
row[6] = event.num_leechs;
|
row[5] = event.num_seeds;
|
||||||
row[7] = event.dlspeed;
|
if (event.num_complete != -1)
|
||||||
row[8] = event.upspeed;
|
row[5] += " (" + event.num_complete + ")";
|
||||||
row[9] = event.eta;
|
data[5] = event.num_seeds;
|
||||||
row[10] = event.ratio;
|
row[6] = event.num_leechs;
|
||||||
if(row[2] != "*")
|
if (event.num_incomplete != -1)
|
||||||
|
row[6] += " (" + event.num_incomplete + ")";
|
||||||
|
data[6] = event.num_leechs;
|
||||||
|
row[7] = friendlyUnit(event.dlspeed, true);
|
||||||
|
data[7] = event.dlspeed;
|
||||||
|
row[8] = friendlyUnit(event.upspeed, true);
|
||||||
|
data[8] = event.upspeed;
|
||||||
|
row[9] = friendlyDuration(event.eta);
|
||||||
|
data[9] = event.eta
|
||||||
|
if(event.ratio == -1)
|
||||||
|
row[10] = "∞";
|
||||||
|
else
|
||||||
|
row[10] = (Math.floor(100 * event.ratio) / 100).toFixed(2); //Don't round up
|
||||||
|
data[10] = event.ratio;
|
||||||
|
if(row[2] != null)
|
||||||
queueing_enabled = true;
|
queueing_enabled = true;
|
||||||
if(!torrent_hashes.contains(event.hash)) {
|
if(!torrent_hashes.contains(event.hash)) {
|
||||||
// New unfinished torrent
|
// New unfinished torrent
|
||||||
torrent_hashes[torrent_hashes.length] = event.hash;
|
torrent_hashes[torrent_hashes.length] = event.hash;
|
||||||
//alert("Inserting row");
|
//alert("Inserting row");
|
||||||
myTable.insertRow(event.hash, row, event.state);
|
myTable.insertRow(event.hash, row, data, event.state);
|
||||||
} else {
|
} else {
|
||||||
// Update torrent data
|
// Update torrent data
|
||||||
myTable.updateRow(event.hash, row, event.state);
|
myTable.updateRow(event.hash, row, data, event.state);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Remove deleted torrents
|
// Remove deleted torrents
|
||||||
|
@ -56,70 +56,23 @@ var dynamicTable = new Class ({
|
|||||||
var reverseSort = tr2.getParent().reverseSort;
|
var reverseSort = tr2.getParent().reverseSort;
|
||||||
switch(i) {
|
switch(i) {
|
||||||
case 1: // Name
|
case 1: // Name
|
||||||
if(!reverseSort) {
|
if(!reverseSort)
|
||||||
if(tr1.getElements('td')[i].get('html') > tr2.getElements('td')[i].get('html'))
|
return tr1.getElements('td')[i].get('html').localeCompare(tr2.getElements('td')[i].get('html'));
|
||||||
return 1;
|
else
|
||||||
return -1;
|
return tr2.getElements('td')[i].get('html').localeCompare(tr1.getElements('td')[i].get('html'));
|
||||||
} else {
|
|
||||||
if(tr1.getElements('td')[i].get('html') < tr2.getElements('td')[i].get('html'))
|
|
||||||
return 1;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
case 2: // Prio
|
case 2: // Prio
|
||||||
var prio1 = tr1.getElements('td')[i].get('html');
|
|
||||||
if(prio1 == '*') prio1 = '-1';
|
|
||||||
var prio2 = tr2.getElements('td')[i].get('html');
|
|
||||||
if(prio2 == '*') prio2 = '-1';
|
|
||||||
if(!reverseSort)
|
|
||||||
return (prio1.toInt() - prio2.toInt());
|
|
||||||
else
|
|
||||||
return (prio2.toInt() - prio1.toInt());
|
|
||||||
case 3: // Size
|
case 3: // Size
|
||||||
case 7: // Up Speed
|
|
||||||
case 8: // Down Speed
|
|
||||||
var sizeStrToFloat = function(mystr) {
|
|
||||||
var val1 = mystr.split(' ');
|
|
||||||
var val1num = val1[0].toFloat()
|
|
||||||
var unit = val1[1];
|
|
||||||
switch(unit) {
|
|
||||||
case '_(TiB)':
|
|
||||||
return val1num*1099511627776;
|
|
||||||
case '_(GiB)':
|
|
||||||
return val1num*1073741824;
|
|
||||||
case '_(MiB)':
|
|
||||||
return val1num*1048576;
|
|
||||||
case '_(KiB)':
|
|
||||||
return val1num*1024;
|
|
||||||
default:
|
|
||||||
return val1num;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if(!reverseSort)
|
|
||||||
return (sizeStrToFloat(tr1.getElements('td')[i].get('html')) - sizeStrToFloat(tr2.getElements('td')[i].get('html')));
|
|
||||||
else
|
|
||||||
return (sizeStrToFloat(tr2.getElements('td')[i].get('html')) - sizeStrToFloat(tr1.getElements('td')[i].get('html')));
|
|
||||||
case 4: // Progress
|
case 4: // Progress
|
||||||
if(!reverseSort)
|
|
||||||
return (tr1.getElements('td')[i].getChildren()[0].getValue() - tr2.getElements('td')[i].getChildren()[0].getValue());
|
|
||||||
else
|
|
||||||
return (tr2.getElements('td')[i].getChildren()[0].getValue() - tr1.getElements('td')[i].getChildren()[0].getValue());
|
|
||||||
case 5: // Seeds
|
case 5: // Seeds
|
||||||
case 6: // Peers
|
case 6: // Peers
|
||||||
if(!reverseSort)
|
case 7: // Up Speed
|
||||||
return (tr1.getElements('td')[i].get('html').split(' ')[0].toInt() - tr2.getElements('td')[i].get('html').split(' ')[0].toInt());
|
case 8: // Down Speed
|
||||||
else
|
case 9: // ETA
|
||||||
return (tr2.getElements('td')[i].get('html').split(' ')[0].toInt() - tr1.getElements('td')[i].get('html').split(' ')[0].toInt());
|
|
||||||
default: // Ratio
|
default: // Ratio
|
||||||
var ratio1 = tr1.getElements('td')[i].get('html');
|
|
||||||
if(ratio1 == '∞')
|
|
||||||
ratio1 = '101.0';
|
|
||||||
var ratio2 = tr2.getElements('td')[i].get('html');
|
|
||||||
if(ratio2 == '∞')
|
|
||||||
ratio2 = '101.0';
|
|
||||||
if(!reverseSort)
|
if(!reverseSort)
|
||||||
return (ratio1.toFloat() - ratio2.toFloat());
|
return (tr1.getElements('td')[i].get('data-raw') - tr2.getElements('td')[i].get('data-raw'));
|
||||||
else
|
else
|
||||||
return (ratio2.toFloat() - ratio1.toFloat());
|
return (tr2.getElements('td')[i].get('data-raw') - tr1.getElements('td')[i].get('data-raw'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -228,7 +181,7 @@ var dynamicTable = new Class ({
|
|||||||
return !tr.hasClass('invisible');
|
return !tr.hasClass('invisible');
|
||||||
},
|
},
|
||||||
|
|
||||||
insertRow: function(id, row, status){
|
insertRow: function(id, row, data, status){
|
||||||
if(this.rows.has(id)) {
|
if(this.rows.has(id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -240,6 +193,8 @@ var dynamicTable = new Class ({
|
|||||||
var td = new Element('td');
|
var td = new Element('td');
|
||||||
if(i==this.progressIndex) {
|
if(i==this.progressIndex) {
|
||||||
td.adopt(new ProgressBar(row[i].toFloat(), {'id': 'pb_'+id, 'width':80}));
|
td.adopt(new ProgressBar(row[i].toFloat(), {'id': 'pb_'+id, 'width':80}));
|
||||||
|
if (typeof data[i] != 'undefined')
|
||||||
|
td.set('data-raw', data[i])
|
||||||
} else {
|
} else {
|
||||||
if(i==0) {
|
if(i==0) {
|
||||||
td.adopt(new Element('img', {'src':row[i], 'class': 'statusIcon'}));
|
td.adopt(new Element('img', {'src':row[i], 'class': 'statusIcon'}));
|
||||||
@ -250,6 +205,8 @@ var dynamicTable = new Class ({
|
|||||||
td.addClass('invisible');
|
td.addClass('invisible');
|
||||||
}
|
}
|
||||||
td.set('html', row[i]);
|
td.set('html', row[i]);
|
||||||
|
if (typeof data[i] != 'undefined')
|
||||||
|
td.set('data-raw', data[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
td.injectInside(tr);
|
td.injectInside(tr);
|
||||||
@ -369,7 +326,7 @@ var dynamicTable = new Class ({
|
|||||||
}, this);
|
}, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
updateRow: function(id, row, status){
|
updateRow: function(id, row, data, status){
|
||||||
if(!this.rows.has(id)) {
|
if(!this.rows.has(id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -388,6 +345,8 @@ var dynamicTable = new Class ({
|
|||||||
tds[i].set('html', row[i]);
|
tds[i].set('html', row[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (typeof data[i] != 'undefined')
|
||||||
|
tds[i].set('data-raw', data[i])
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// Row was hidden, check if it was selected
|
// Row was hidden, check if it was selected
|
||||||
|
78
src/webui/www/public/scripts/misc.js
Normal file
78
src/webui/www/public/scripts/misc.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* JS counterpart of the function in src/misc.cpp
|
||||||
|
*/
|
||||||
|
function friendlyUnit(value, isSpeed) {
|
||||||
|
units = [
|
||||||
|
"_(B)",
|
||||||
|
"_(KiB)",
|
||||||
|
"_(MiB)",
|
||||||
|
"_(GiB)",
|
||||||
|
"_(TiB)",
|
||||||
|
];
|
||||||
|
|
||||||
|
if (value < 0)
|
||||||
|
return "_(Unknown)";
|
||||||
|
var i = 0;
|
||||||
|
while (value >= 1024. && i++ < 6)
|
||||||
|
value /= 1024.;
|
||||||
|
var ret;
|
||||||
|
if (i == 0)
|
||||||
|
ret = value.toFixed(2) + " " + units[0];
|
||||||
|
else
|
||||||
|
ret = value.toFixed(2) + " " + units[i];
|
||||||
|
if (isSpeed)
|
||||||
|
ret += "_(/s)";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JS counterpart of the function in src/misc.cpp
|
||||||
|
*/
|
||||||
|
function friendlyDuration(seconds) {
|
||||||
|
var MAX_ETA = 8640000;
|
||||||
|
if (seconds < 0 || seconds >= MAX_ETA)
|
||||||
|
return "∞";
|
||||||
|
if (seconds == 0)
|
||||||
|
return "0";
|
||||||
|
if (seconds < 60)
|
||||||
|
return "< " + "_(%1m)".replace("%1", "1"); //translation of "< 1m" not working
|
||||||
|
var minutes = seconds / 60;
|
||||||
|
if (minutes < 60)
|
||||||
|
return "_(%1m)".replace("%1", parseInt(minutes));
|
||||||
|
var hours = minutes / 60;
|
||||||
|
minutes = minutes - hours*60;
|
||||||
|
if (hours < 24)
|
||||||
|
return "_(%1h %2m)".replace("%1", parseInt(hours)).replace("%2", parseInt(minutes))
|
||||||
|
var days = hours / 24;
|
||||||
|
hours = hours - days * 24;
|
||||||
|
if (days < 100)
|
||||||
|
return "_(%1d %2h)".replace("%1", parseInt(days)).replace("%2", parseInt(hours))
|
||||||
|
return "∞";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
|
||||||
|
*/
|
||||||
|
if (!Date.prototype.toISOString) {
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
function pad(number) {
|
||||||
|
if (number < 10) {
|
||||||
|
return '0' + number;
|
||||||
|
}
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
Date.prototype.toISOString = function() {
|
||||||
|
return this.getUTCFullYear() +
|
||||||
|
'-' + pad(this.getUTCMonth() + 1) +
|
||||||
|
'-' + pad(this.getUTCDate()) +
|
||||||
|
'T' + pad(this.getUTCHours()) +
|
||||||
|
':' + pad(this.getUTCMinutes()) +
|
||||||
|
':' + pad(this.getUTCSeconds()) +
|
||||||
|
'.' + (this.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5) +
|
||||||
|
'Z';
|
||||||
|
};
|
||||||
|
|
||||||
|
}());
|
||||||
|
}
|
@ -10,7 +10,7 @@
|
|||||||
<th onClick="setSortedColumn(6);" style="cursor: pointer;">_(Peers)</th>
|
<th onClick="setSortedColumn(6);" style="cursor: pointer;">_(Peers)</th>
|
||||||
<th onClick="setSortedColumn(7);" style="cursor: pointer;">_(Down Speed)</th>
|
<th onClick="setSortedColumn(7);" style="cursor: pointer;">_(Down Speed)</th>
|
||||||
<th onClick="setSortedColumn(8);" style="cursor: pointer;">_(Up Speed)</th>
|
<th onClick="setSortedColumn(8);" style="cursor: pointer;">_(Up Speed)</th>
|
||||||
<th>_(ETA)</th>
|
<th onClick="setSortedColumn(9);" style="cursor: pointer;">_(ETA)</th>
|
||||||
<th onClick="setSortedColumn(10);" style="cursor: pointer;">_(Ratio)</th>
|
<th onClick="setSortedColumn(10);" style="cursor: pointer;">_(Ratio)</th>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user