mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-10-22 10:46:04 +03:00
Merge pull request #5547 from buinsky/master
WebUI: Implement adjustable dynamic table columns
This commit is contained in:
commit
87e454cc6d
10 changed files with 761 additions and 285 deletions
|
@ -244,7 +244,7 @@ void AbstractWebApplication::translateDocument(QString& data)
|
||||||
"options_imp", "Preferences", "TrackersAdditionDlg", "ScanFoldersModel",
|
"options_imp", "Preferences", "TrackersAdditionDlg", "ScanFoldersModel",
|
||||||
"PropTabBar", "TorrentModel", "downloadFromURL", "MainWindow", "misc",
|
"PropTabBar", "TorrentModel", "downloadFromURL", "MainWindow", "misc",
|
||||||
"StatusBar", "AboutDlg", "about", "PeerListWidget", "StatusFiltersWidget",
|
"StatusBar", "AboutDlg", "about", "PeerListWidget", "StatusFiltersWidget",
|
||||||
"CategoryFiltersList"
|
"CategoryFiltersList", "TransferListDelegate"
|
||||||
};
|
};
|
||||||
const size_t context_count = sizeof(contexts) / sizeof(contexts[0]);
|
const size_t context_count = sizeof(contexts) / sizeof(contexts[0]);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
|
@ -109,6 +109,19 @@ static const char KEY_TORRENT_FORCE_START[] = "force_start";
|
||||||
static const char KEY_TORRENT_SAVE_PATH[] = "save_path";
|
static const char KEY_TORRENT_SAVE_PATH[] = "save_path";
|
||||||
static const char KEY_TORRENT_ADDED_ON[] = "added_on";
|
static const char KEY_TORRENT_ADDED_ON[] = "added_on";
|
||||||
static const char KEY_TORRENT_COMPLETION_ON[] = "completion_on";
|
static const char KEY_TORRENT_COMPLETION_ON[] = "completion_on";
|
||||||
|
static const char KEY_TORRENT_TRACKER[] = "tracker";
|
||||||
|
static const char KEY_TORRENT_DL_LIMIT[] = "dl_limit";
|
||||||
|
static const char KEY_TORRENT_UP_LIMIT[] = "up_limit";
|
||||||
|
static const char KEY_TORRENT_AMOUNT_DOWNLOADED[] = "downloaded";
|
||||||
|
static const char KEY_TORRENT_AMOUNT_UPLOADED[] = "uploaded";
|
||||||
|
static const char KEY_TORRENT_AMOUNT_DOWNLOADED_SESSION[] = "downloaded_session";
|
||||||
|
static const char KEY_TORRENT_AMOUNT_UPLOADED_SESSION[] = "uploaded_session";
|
||||||
|
static const char KEY_TORRENT_AMOUNT_LEFT[] = "remaining";
|
||||||
|
static const char KEY_TORRENT_AMOUNT_COMPLETED[] = "completed";
|
||||||
|
static const char KEY_TORRENT_RATIO_LIMIT[] = "ratio_limit";
|
||||||
|
static const char KEY_TORRENT_LAST_SEEN_COMPLETE_TIME[] = "seen_complete";
|
||||||
|
static const char KEY_TORRENT_LAST_ACTIVITY_TIME[] = "last_activity";
|
||||||
|
static const char KEY_TORRENT_TOTAL_SIZE[] = "total_size";
|
||||||
|
|
||||||
// Peer keys
|
// Peer keys
|
||||||
static const char KEY_PEER_IP[] = "ip";
|
static const char KEY_PEER_IP[] = "ip";
|
||||||
|
@ -125,6 +138,7 @@ static const char KEY_PEER_CONNECTION_TYPE[] = "connection";
|
||||||
static const char KEY_PEER_FLAGS[] = "flags";
|
static const char KEY_PEER_FLAGS[] = "flags";
|
||||||
static const char KEY_PEER_FLAGS_DESCRIPTION[] = "flags_desc";
|
static const char KEY_PEER_FLAGS_DESCRIPTION[] = "flags_desc";
|
||||||
static const char KEY_PEER_RELEVANCE[] = "relevance";
|
static const char KEY_PEER_RELEVANCE[] = "relevance";
|
||||||
|
static const char KEY_PEER_FILES[] = "files";
|
||||||
|
|
||||||
// Tracker keys
|
// Tracker keys
|
||||||
static const char KEY_TRACKER_URL[] = "url";
|
static const char KEY_TRACKER_URL[] = "url";
|
||||||
|
@ -347,6 +361,21 @@ QByteArray btjson::getTorrents(QString filter, QString category,
|
||||||
* - "state": Torrent state
|
* - "state": Torrent state
|
||||||
* - "seq_dl": Torrent sequential download state
|
* - "seq_dl": Torrent sequential download state
|
||||||
* - "f_l_piece_prio": Torrent first last piece priority state
|
* - "f_l_piece_prio": Torrent first last piece priority state
|
||||||
|
* - "completion_on": Torrent copletion time
|
||||||
|
* - "tracker": Torrent tracker
|
||||||
|
* - "dl_limit": Torrent download limit
|
||||||
|
* - "up_limit": Torrent upload limit
|
||||||
|
* - "downloaded": Amount of data downloaded
|
||||||
|
* - "uploaded": Amount of data uploaded
|
||||||
|
* - "downloaded_session": Amount of data downloaded since program open
|
||||||
|
* - "uploaded_session": Amount of data uploaded since program open
|
||||||
|
* - "amount_left": Amount of data left to download
|
||||||
|
* - "save_path": Torrent save path
|
||||||
|
* - "completed": Amount of data completed
|
||||||
|
* - "ratio_limit": Upload share ratio limit
|
||||||
|
* - "seen_complete": Indicates the time when the torrent was last seen complete/whole
|
||||||
|
* - "last_activity": Last time when a chunk was downloaded/uploaded
|
||||||
|
* - "total_size": Size including unwanted data
|
||||||
* Server state map may contain the following keys:
|
* Server state map may contain the following keys:
|
||||||
* - "connection_status": connection status
|
* - "connection_status": connection status
|
||||||
* - "dht_nodes": DHT nodes count
|
* - "dht_nodes": DHT nodes count
|
||||||
|
@ -369,6 +398,16 @@ QByteArray btjson::getSyncMainData(int acceptedResponseId, QVariantMap &lastData
|
||||||
foreach (BitTorrent::TorrentHandle *const torrent, session->torrents()) {
|
foreach (BitTorrent::TorrentHandle *const torrent, session->torrents()) {
|
||||||
QVariantMap map = toMap(torrent);
|
QVariantMap map = toMap(torrent);
|
||||||
map.remove(KEY_TORRENT_HASH);
|
map.remove(KEY_TORRENT_HASH);
|
||||||
|
|
||||||
|
// Calculated last activity time can differ from actual value by up to 10 seconds (this is a libtorrent issue).
|
||||||
|
// So we don't need unnecessary updates of last activity time in response.
|
||||||
|
if (lastData.contains("torrents") && lastData["torrents"].toHash().contains(torrent->hash()) &&
|
||||||
|
lastData["torrents"].toHash()[torrent->hash()].toMap().contains(KEY_TORRENT_LAST_ACTIVITY_TIME)) {
|
||||||
|
uint lastValue = lastData["torrents"].toHash()[torrent->hash()].toMap()[KEY_TORRENT_LAST_ACTIVITY_TIME].toUInt();
|
||||||
|
if (qAbs((int)(lastValue - map[KEY_TORRENT_LAST_ACTIVITY_TIME].toUInt())) < 15)
|
||||||
|
map[KEY_TORRENT_LAST_ACTIVITY_TIME] = lastValue;
|
||||||
|
}
|
||||||
|
|
||||||
torrents[torrent->hash()] = map;
|
torrents[torrent->hash()] = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,6 +468,8 @@ QByteArray btjson::getSyncTorrentPeersData(int acceptedResponseId, QString hash,
|
||||||
peer[KEY_PEER_FLAGS] = pi.flags();
|
peer[KEY_PEER_FLAGS] = pi.flags();
|
||||||
peer[KEY_PEER_FLAGS_DESCRIPTION] = pi.flagsDescription();
|
peer[KEY_PEER_FLAGS_DESCRIPTION] = pi.flagsDescription();
|
||||||
peer[KEY_PEER_RELEVANCE] = pi.relevance();
|
peer[KEY_PEER_RELEVANCE] = pi.relevance();
|
||||||
|
peer[KEY_PEER_FILES] = torrent->info().filesForPiece(pi.downloadingPieceIndex()).join(QLatin1String("\n"));
|
||||||
|
|
||||||
peers[pi.address().ip.toString() + ":" + QString::number(pi.address().port)] = peer;
|
peers[pi.address().ip.toString() + ":" + QString::number(pi.address().port)] = peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -723,6 +764,27 @@ QVariantMap toMap(BitTorrent::TorrentHandle *const torrent)
|
||||||
ret[KEY_TORRENT_SAVE_PATH] = Utils::Fs::toNativePath(torrent->savePath());
|
ret[KEY_TORRENT_SAVE_PATH] = Utils::Fs::toNativePath(torrent->savePath());
|
||||||
ret[KEY_TORRENT_ADDED_ON] = torrent->addedTime().toTime_t();
|
ret[KEY_TORRENT_ADDED_ON] = torrent->addedTime().toTime_t();
|
||||||
ret[KEY_TORRENT_COMPLETION_ON] = torrent->completedTime().toTime_t();
|
ret[KEY_TORRENT_COMPLETION_ON] = torrent->completedTime().toTime_t();
|
||||||
|
ret[KEY_TORRENT_TRACKER] = torrent->currentTracker();
|
||||||
|
ret[KEY_TORRENT_DL_LIMIT] = torrent->downloadLimit();
|
||||||
|
ret[KEY_TORRENT_UP_LIMIT] = torrent->uploadLimit();
|
||||||
|
ret[KEY_TORRENT_AMOUNT_DOWNLOADED] = torrent->totalDownload();
|
||||||
|
ret[KEY_TORRENT_AMOUNT_UPLOADED] = torrent->totalUpload();
|
||||||
|
ret[KEY_TORRENT_AMOUNT_DOWNLOADED_SESSION] = torrent->totalPayloadDownload();
|
||||||
|
ret[KEY_TORRENT_AMOUNT_UPLOADED_SESSION] = torrent->totalPayloadUpload();
|
||||||
|
ret[KEY_TORRENT_AMOUNT_LEFT] = torrent->incompletedSize();
|
||||||
|
ret[KEY_TORRENT_AMOUNT_COMPLETED] = torrent->completedSize();
|
||||||
|
ret[KEY_TORRENT_RATIO_LIMIT] = torrent->maxRatio();
|
||||||
|
ret[KEY_TORRENT_LAST_SEEN_COMPLETE_TIME] = torrent->lastSeenComplete().toTime_t();
|
||||||
|
|
||||||
|
if (torrent->isPaused() || torrent->isChecking())
|
||||||
|
ret[KEY_TORRENT_LAST_ACTIVITY_TIME] = 0;
|
||||||
|
else {
|
||||||
|
QDateTime dt = QDateTime::currentDateTime();
|
||||||
|
dt = dt.addSecs(-torrent->timeSinceActivity());
|
||||||
|
ret[KEY_TORRENT_LAST_ACTIVITY_TIME] = dt.toTime_t();
|
||||||
|
}
|
||||||
|
|
||||||
|
ret[KEY_TORRENT_TOTAL_SIZE] = torrent->totalSize();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@
|
||||||
<li class="separator"><a href="#Delete"><img src="theme/list-remove" alt="QBT_TR(Delete)QBT_TR"/> QBT_TR(Delete)QBT_TR</a></li>
|
<li class="separator"><a href="#Delete"><img src="theme/list-remove" alt="QBT_TR(Delete)QBT_TR"/> QBT_TR(Delete)QBT_TR</a></li>
|
||||||
<li class="separator">
|
<li class="separator">
|
||||||
<a href="#Category" class="arrow-right"><img src="theme/view-categories" alt="QBT_TR(Category)QBT_TR"/> QBT_TR(Category)QBT_TR</a>
|
<a href="#Category" class="arrow-right"><img src="theme/view-categories" alt="QBT_TR(Category)QBT_TR"/> QBT_TR(Category)QBT_TR</a>
|
||||||
<ul id="contextCategoryList"></ul>
|
<ul id="contextCategoryList" class="scrollableMenu"></ul>
|
||||||
</li>
|
</li>
|
||||||
<li id="queueingMenuItems" class="separator">
|
<li id="queueingMenuItems" class="separator">
|
||||||
<a href="#priority" class="arrow-right"><span style="display: inline-block; width:16px"></span> QBT_TR(Priority)QBT_TR</a>
|
<a href="#priority" class="arrow-right"><span style="display: inline-block; width:16px"></span> QBT_TR(Priority)QBT_TR</a>
|
||||||
|
|
|
@ -2,94 +2,93 @@
|
||||||
|
|
||||||
/**************************************************************
|
/**************************************************************
|
||||||
|
|
||||||
Dynamic Table
|
Dynamic Table
|
||||||
v 0.4
|
v 0.4
|
||||||
|
|
||||||
**************************************************************/
|
**************************************************************/
|
||||||
|
.dynamicTable tbody tr {
|
||||||
#properties #torrentFiles table,
|
background-color: #fff;
|
||||||
#properties #trackers table,
|
|
||||||
#transferList table {
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#properties #torrentFiles th,
|
.dynamicTable tbody tr:nth-child(even),
|
||||||
#properties #trackers th,
|
.dynamicTable tbody tr.alt {
|
||||||
#transferList th {
|
background-color: #eee;
|
||||||
background-color: #eee;
|
|
||||||
padding: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#properties #torrentFiles tr,
|
#transferList .dynamicTable td {
|
||||||
#properties #trackers tr,
|
padding: 0 2px;
|
||||||
#transferList tr {
|
|
||||||
background-color: #fff;
|
|
||||||
padding: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dynamicTable tbody tr.selected {
|
||||||
#torrentsTable tr:nth-child(even),
|
background-color: #354158;
|
||||||
#torrentPeersTable tr:nth-child(even),
|
color: #fff;
|
||||||
#filesTable tr:nth-child(even),
|
|
||||||
#properties #torrentFiles tr.alt,
|
|
||||||
#properties #trackers tr.alt,
|
|
||||||
#transferList tr.alt {
|
|
||||||
background-color: #eee;
|
|
||||||
padding: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#properties #torrentFiles td,
|
.dynamicTable tbody tr:hover {
|
||||||
#properties #trackers td,
|
background-color: #ee6600;
|
||||||
#transferList td {
|
color: #fff;
|
||||||
padding: 0 2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#properties #torrentFiles tr.selected,
|
#transferList tr:hover {
|
||||||
#properties #trackers tr.selected,
|
cursor: pointer;
|
||||||
#transferList tr.selected {
|
|
||||||
background-color: #415A8D;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
#torrentPeersTable tr.selected {
|
|
||||||
background-color: #354158;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#torrentsTable tr:hover,
|
|
||||||
#torrentPeersTable tr:hover,
|
|
||||||
#filesTable tr:hover,
|
|
||||||
#properties #torrentFiles tr.over,
|
|
||||||
#properties #trackers tr.over,
|
|
||||||
#transferList tr.over {
|
|
||||||
background-color: #ee6600;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#torrentsTable tr:hover,
|
|
||||||
#properties #torrentFiles tr.over,
|
|
||||||
#properties #trackers tr.over,
|
|
||||||
#transferList tr.over {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#transferList img.statusIcon {
|
#transferList img.statusIcon {
|
||||||
height: 1.3em;
|
height: 1.3em;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
margin-bottom: -1px;
|
||||||
|
|
||||||
#trackers th,
|
|
||||||
#trackers td,
|
|
||||||
#torrentFiles th,
|
|
||||||
#torrentFiles td,
|
|
||||||
#transferList th,
|
|
||||||
#transferList td {
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
max-width: 300px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.dynamicTableHeader {
|
tr.dynamicTableHeader {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dynamicTable {
|
||||||
|
table-layout: fixed;
|
||||||
|
width :1%;
|
||||||
|
padding: 0;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamicTable th {
|
||||||
|
background-color: #eee;
|
||||||
|
padding: 4px;
|
||||||
|
white-space: nowrap;
|
||||||
|
border-right-color: #ccc;
|
||||||
|
border-right-style: solid;
|
||||||
|
border-right-width: 1px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamicTable td {
|
||||||
|
padding:0px 4px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamicTable thead tr {
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamicTable th,
|
||||||
|
.dynamicTable td {
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamicTableFixedHeaderDiv {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamicTableDiv {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamicTableDiv thead th {
|
||||||
|
line-height: 0px !important;
|
||||||
|
height: 0px !important;
|
||||||
|
padding-top: 0px !important;
|
||||||
|
padding-bottom: 0px !important;
|
||||||
|
}
|
||||||
|
|
|
@ -165,12 +165,25 @@ a.propButton img {
|
||||||
margin-bottom: -4px;
|
margin-bottom: -4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scrollableMenu {
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
/* context menu specific */
|
/* context menu specific */
|
||||||
|
|
||||||
.contextMenu { border:1px solid #999; padding:0; background:#eee; list-style-type:none; display:none;}
|
.contextMenu { border:1px solid #999; padding:0; background:#eee; list-style-type:none; display:none;}
|
||||||
.contextMenu .separator { border-top:1px solid #999; }
|
.contextMenu .separator { border-top:1px solid #999; }
|
||||||
.contextMenu li { margin:0; padding:0;}
|
.contextMenu li { margin:0; padding:0;}
|
||||||
.contextMenu li a { display:block; padding:5px 10px 5px 5px; font-size:12px; text-decoration:none; font-family:tahoma,arial,sans-serif; color:#000; }
|
.contextMenu li a {
|
||||||
|
display: block;
|
||||||
|
padding: 5px 20px 5px 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-family: tahoma,arial,sans-serif;
|
||||||
|
color: #000;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
.contextMenu li a:hover { background-color:#ddd; }
|
.contextMenu li a:hover { background-color:#ddd; }
|
||||||
.contextMenu li a.disabled { color:#ccc; font-style:italic; }
|
.contextMenu li a.disabled { color:#ccc; font-style:italic; }
|
||||||
.contextMenu li a.disabled:hover { background-color:#eee; }
|
.contextMenu li a.disabled:hover { background-color:#eee; }
|
||||||
|
@ -389,7 +402,7 @@ td.generalLabel {
|
||||||
margin-bottom: -3px;
|
margin-bottom: -3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.torrentTable {
|
.unselectable {
|
||||||
-webkit-touch-callout: none;
|
-webkit-touch-callout: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-khtml-user-select: none;
|
-khtml-user-select: none;
|
||||||
|
@ -398,20 +411,6 @@ td.generalLabel {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.torrentTable th {
|
|
||||||
padding: 5px 10px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.torrentTable td {
|
|
||||||
padding: 0px 3px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.torrentTable thead tr {
|
|
||||||
background-color: #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
#prop_general {
|
#prop_general {
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
|
|
||||||
<div id="prop_trackers" class="invisible">
|
<div id="prop_trackers" class="invisible">
|
||||||
<div id="trackers">
|
<div id="trackers">
|
||||||
<table class="torrentTable" cellpadding="0" cellspacing="0" style="width: 100%">
|
<table class="dynamicTable" style="width: 100%">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 30%;">QBT_TR(URL)QBT_TR <img src="theme/list-add" id="addTrackersPlus"/></th>
|
<th style="width: 30%;">QBT_TR(URL)QBT_TR <img src="theme/list-add" id="addTrackersPlus"/></th>
|
||||||
|
@ -65,19 +65,27 @@
|
||||||
|
|
||||||
<div id="prop_peers" class="invisible">
|
<div id="prop_peers" class="invisible">
|
||||||
<div id="peers">
|
<div id="peers">
|
||||||
<table class="torrentTable" cellpadding="0" cellspacing="0" style="width: 100%">
|
<div id="torrentPeersTableFixedHeaderDiv" class="dynamicTableFixedHeaderDiv">
|
||||||
<thead>
|
<table class="dynamicTable" style="position:relative;">
|
||||||
<tr id="torrentPeersTableHeader" class="dynamicTableHeader">
|
<thead>
|
||||||
</tr>
|
<tr class="dynamicTableHeader"></tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="torrentPeersTable"></tbody>
|
</table>
|
||||||
</table>
|
</div>
|
||||||
|
<div id="torrentPeersTableDiv" class="dynamicTableDiv">
|
||||||
|
<table class="dynamicTable">
|
||||||
|
<thead>
|
||||||
|
<tr class="dynamicTableHeader"></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="prop_webseeds" class="invisible">
|
<div id="prop_webseeds" class="invisible">
|
||||||
<div id="webseeds">
|
<div id="webseeds">
|
||||||
<table class="torrentTable" cellpadding="0" cellspacing="0" style="width: 100%">
|
<table class="dynamicTable" style="width: 100%">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>QBT_TR(URL)QBT_TR</th>
|
<th>QBT_TR(URL)QBT_TR</th>
|
||||||
|
@ -90,7 +98,7 @@
|
||||||
|
|
||||||
<div id="prop_files" class="invisible">
|
<div id="prop_files" class="invisible">
|
||||||
<div id="torrentFiles">
|
<div id="torrentFiles">
|
||||||
<table class="torrentTable" cellpadding="0" cellspacing="0" style="width: 100%">
|
<table class="dynamicTable" style="width: 100%">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 30px; border-right: 0"><input type="checkbox" id="tristate_cb" style="display: none;" onclick="javascript:switchCBState()" /><label id="all_files_cb" class="tristate" for="tristate_cb"></label></th>
|
<th style="width: 30px; border-right: 0"><input type="checkbox" id="tristate_cb" style="display: none;" onclick="javascript:switchCBState()" /><label id="all_files_cb" class="tristate" for="tristate_cb"></label></th>
|
||||||
|
@ -106,6 +114,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
torrentPeersTable.setup('torrentPeersTable', 'torrentPeersTableHeader', null);
|
torrentPeersTable.setup('torrentPeersTableDiv', 'torrentPeersTableFixedHeaderDiv', null);
|
||||||
$(getLocalStorageItem('selected_tab', 'PropGeneralLink')).click();
|
$(getLocalStorageItem('selected_tab', 'PropGeneralLink')).click();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -57,6 +57,11 @@ var ContextMenu = new Class({
|
||||||
adjustMenuPosition: function(e) {
|
adjustMenuPosition: function(e) {
|
||||||
this.updateMenuItems();
|
this.updateMenuItems();
|
||||||
|
|
||||||
|
var scrollableMenuMaxHeight = document.documentElement.clientHeight * 0.75;
|
||||||
|
|
||||||
|
if (this.menu.hasClass('scrollableMenu'))
|
||||||
|
this.menu.setStyle('max-height', scrollableMenuMaxHeight);
|
||||||
|
|
||||||
// draw the menu off-screen to know the menu dimentions
|
// draw the menu off-screen to know the menu dimentions
|
||||||
this.menu.setStyles({
|
this.menu.setStyles({
|
||||||
left: '-999em',
|
left: '-999em',
|
||||||
|
@ -69,7 +74,7 @@ var ContextMenu = new Class({
|
||||||
if (xPos + this.menu.offsetWidth > document.documentElement.clientWidth)
|
if (xPos + this.menu.offsetWidth > document.documentElement.clientWidth)
|
||||||
xPos -= this.menu.offsetWidth;
|
xPos -= this.menu.offsetWidth;
|
||||||
if (yPos + this.menu.offsetHeight > document.documentElement.clientHeight)
|
if (yPos + this.menu.offsetHeight > document.documentElement.clientHeight)
|
||||||
yPos -= this.menu.offsetHeight;
|
yPos = document.documentElement.clientHeight - this.menu.offsetHeight;
|
||||||
if (xPos < 0)
|
if (xPos < 0)
|
||||||
xPos = 0;
|
xPos = 0;
|
||||||
if (yPos < 0)
|
if (yPos < 0)
|
||||||
|
@ -85,6 +90,8 @@ var ContextMenu = new Class({
|
||||||
var uls = this.menu.getElementsByTagName('ul');
|
var uls = this.menu.getElementsByTagName('ul');
|
||||||
for (var i = 0; i < uls.length; i++) {
|
for (var i = 0; i < uls.length; i++) {
|
||||||
var ul = uls[i];
|
var ul = uls[i];
|
||||||
|
if (ul.hasClass('scrollableMenu'))
|
||||||
|
ul.setStyle('max-height', scrollableMenuMaxHeight);
|
||||||
var rectParent = ul.parentNode.getBoundingClientRect();
|
var rectParent = ul.parentNode.getBoundingClientRect();
|
||||||
var xPosOrigin = rectParent.left;
|
var xPosOrigin = rectParent.left;
|
||||||
var yPosOrigin = rectParent.bottom;
|
var yPosOrigin = rectParent.bottom;
|
||||||
|
@ -93,7 +100,7 @@ var ContextMenu = new Class({
|
||||||
if (xPos + ul.offsetWidth > document.documentElement.clientWidth)
|
if (xPos + ul.offsetWidth > document.documentElement.clientWidth)
|
||||||
xPos -= (ul.offsetWidth + rectParent.width - 2);
|
xPos -= (ul.offsetWidth + rectParent.width - 2);
|
||||||
if (yPos + ul.offsetHeight > document.documentElement.clientHeight)
|
if (yPos + ul.offsetHeight > document.documentElement.clientHeight)
|
||||||
yPos -= (ul.offsetHeight - rectParent.height - 2);
|
yPos = document.documentElement.clientHeight - ul.offsetHeight;
|
||||||
if (xPos < 0)
|
if (xPos < 0)
|
||||||
xPos = 0;
|
xPos = 0;
|
||||||
if (yPos < 0)
|
if (yPos < 0)
|
||||||
|
@ -228,7 +235,7 @@ var ContextMenu = new Class({
|
||||||
//execute an action
|
//execute an action
|
||||||
execute: function (action, element) {
|
execute: function (action, element) {
|
||||||
if (this.options.actions[action]) {
|
if (this.options.actions[action]) {
|
||||||
this.options.actions[action](element, this);
|
this.options.actions[action](element, this, action);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,35 +31,303 @@
|
||||||
|
|
||||||
**************************************************************/
|
**************************************************************/
|
||||||
|
|
||||||
|
var DynamicTableHeaderContextMenuClass = null;
|
||||||
|
|
||||||
var DynamicTable = new Class({
|
var DynamicTable = new Class({
|
||||||
|
|
||||||
initialize : function () {},
|
initialize : function () {},
|
||||||
|
|
||||||
setup : function (tableId, tableHeaderId, context_menu) {
|
setup : function (dynamicTableDivId, dynamicTableFixedHeaderDivId, contextMenu) {
|
||||||
this.tableId = tableId;
|
this.dynamicTableDivId = dynamicTableDivId;
|
||||||
this.tableHeaderId = tableHeaderId;
|
this.dynamicTableFixedHeaderDivId = dynamicTableFixedHeaderDivId;
|
||||||
this.table = $(tableId);
|
this.fixedTableHeader = $(dynamicTableFixedHeaderDivId).getElements('tr')[0];
|
||||||
|
this.hiddenTableHeader = $(dynamicTableDivId).getElements('tr')[0];
|
||||||
|
this.tableBody = $(dynamicTableDivId).getElements('tbody')[0];
|
||||||
this.rows = new Hash();
|
this.rows = new Hash();
|
||||||
this.cur = new Array();
|
this.selectedRows = new Array();
|
||||||
this.columns = new Array();
|
this.columns = new Array();
|
||||||
this.context_menu = context_menu;
|
this.contextMenu = contextMenu;
|
||||||
this.sortedColumn = getLocalStorageItem('sorted_column_' + this.tableId, 0);
|
this.sortedColumn = getLocalStorageItem('sorted_column_' + this.dynamicTableDivId, 0);
|
||||||
this.reverseSort = getLocalStorageItem('reverse_sort_' + this.tableId, '0');
|
this.reverseSort = getLocalStorageItem('reverse_sort_' + this.dynamicTableDivId, '0');
|
||||||
this.initColumns();
|
this.initColumns();
|
||||||
this.loadColumnsOrder();
|
this.loadColumnsOrder();
|
||||||
this.updateHeader();
|
this.updateTableHeaders();
|
||||||
|
this.setupCommonEvents();
|
||||||
|
this.setupHeaderEvents();
|
||||||
|
this.setupHeaderMenu();
|
||||||
|
},
|
||||||
|
|
||||||
|
setupCommonEvents : function () {
|
||||||
|
var scrollFn = function() {
|
||||||
|
$(this.dynamicTableFixedHeaderDivId).getElements('table')[0].style.left =
|
||||||
|
-$(this.dynamicTableDivId).scrollLeft + 'px';
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
$(this.dynamicTableDivId).addEvent('scroll', scrollFn);
|
||||||
|
|
||||||
|
var resizeFn = function() {
|
||||||
|
var panel = $(this.dynamicTableDivId).getParent('.panel');
|
||||||
|
var h = panel.getBoundingClientRect().height - $(this.dynamicTableFixedHeaderDivId).getBoundingClientRect().height;
|
||||||
|
$(this.dynamicTableDivId).style.height = h + 'px';
|
||||||
|
|
||||||
|
// Workaround due to inaccurate calculation of elements heights by browser
|
||||||
|
|
||||||
|
var n = 2;
|
||||||
|
|
||||||
|
while (panel.clientWidth != panel.offsetWidth && n > 0) { // is panel vertical scrollbar visible ?
|
||||||
|
n--;
|
||||||
|
h -= 0.5;
|
||||||
|
$(this.dynamicTableDivId).style.height = h + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastPanelHeight = panel.getBoundingClientRect().height;
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
$(this.dynamicTableDivId).getParent('.panel').addEvent('resize', resizeFn);
|
||||||
|
|
||||||
|
this.lastPanelHeight = 0;
|
||||||
|
|
||||||
|
// Workaround. Resize event is called not always (for example it isn't called when browser window changes it's size)
|
||||||
|
|
||||||
|
var checkResizeFn = function() {
|
||||||
|
var panel = $(this.dynamicTableDivId).getParent('.panel');
|
||||||
|
if (this.lastPanelHeight != panel.getBoundingClientRect().height) {
|
||||||
|
this.lastPanelHeight = panel.getBoundingClientRect().height;
|
||||||
|
panel.fireEvent('resize');
|
||||||
|
}
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
setInterval(checkResizeFn, 500);
|
||||||
|
},
|
||||||
|
|
||||||
|
setupHeaderEvents : function () {
|
||||||
|
this.currentHeaderAction = '';
|
||||||
|
this.canResize = false;
|
||||||
|
|
||||||
|
var resetElementBorderStyle = function (el, side) {
|
||||||
|
if (side === 'left' || side !== 'right') {
|
||||||
|
el.setStyle('border-left-style', '');
|
||||||
|
el.setStyle('border-left-color', '');
|
||||||
|
el.setStyle('border-left-width', '');
|
||||||
|
}
|
||||||
|
if (side === 'right' || side !== 'left') {
|
||||||
|
el.setStyle('border-right-style', '');
|
||||||
|
el.setStyle('border-right-color', '');
|
||||||
|
el.setStyle('border-right-width', '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var mouseMoveFn = function (e) {
|
||||||
|
var brect = e.target.getBoundingClientRect();
|
||||||
|
var mouseXRelative = e.event.clientX - brect.left;
|
||||||
|
if (this.currentHeaderAction === '') {
|
||||||
|
if (brect.width - mouseXRelative < 5) {
|
||||||
|
this.resizeTh = e.target;
|
||||||
|
this.canResize = true;
|
||||||
|
e.target.getParent("tr").style.cursor = 'col-resize';
|
||||||
|
}
|
||||||
|
else if ((mouseXRelative < 5) && e.target.getPrevious('[class=""]')) {
|
||||||
|
this.resizeTh = e.target.getPrevious('[class=""]');
|
||||||
|
this.canResize = true;
|
||||||
|
e.target.getParent("tr").style.cursor = 'col-resize';
|
||||||
|
} else {
|
||||||
|
this.canResize = false;
|
||||||
|
e.target.getParent("tr").style.cursor = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.currentHeaderAction === 'drag') {
|
||||||
|
var previousVisibleSibling = e.target.getPrevious('[class=""]');
|
||||||
|
var borderChangeElement = previousVisibleSibling;
|
||||||
|
var changeBorderSide = 'right';
|
||||||
|
|
||||||
|
if (mouseXRelative > brect.width / 2) {
|
||||||
|
borderChangeElement = e.target;
|
||||||
|
this.dropSide = 'right';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.dropSide = 'left';
|
||||||
|
}
|
||||||
|
|
||||||
|
e.target.getParent("tr").style.cursor = 'move';
|
||||||
|
|
||||||
|
if (!previousVisibleSibling) { // right most column
|
||||||
|
borderChangeElement = e.target;
|
||||||
|
|
||||||
|
if (mouseXRelative <= brect.width / 2)
|
||||||
|
changeBorderSide = 'left';
|
||||||
|
}
|
||||||
|
|
||||||
|
borderChangeElement.setStyle('border-' + changeBorderSide + '-style', 'solid');
|
||||||
|
borderChangeElement.setStyle('border-' + changeBorderSide + '-color', '#e60');
|
||||||
|
borderChangeElement.setStyle('border-' + changeBorderSide + '-width', 'initial');
|
||||||
|
|
||||||
|
resetElementBorderStyle(borderChangeElement, changeBorderSide === 'right' ? 'left' : 'right');
|
||||||
|
|
||||||
|
borderChangeElement.getSiblings('[class=""]').each(function(el){
|
||||||
|
resetElementBorderStyle(el);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.lastHoverTh = e.target;
|
||||||
|
this.lastClientX = e.event.clientX;
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
var mouseOutFn = function (e) {
|
||||||
|
resetElementBorderStyle(e.target);
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
var onBeforeStart = function (el) {
|
||||||
|
this.clickedTh = el;
|
||||||
|
this.currentHeaderAction = 'start';
|
||||||
|
this.dragMovement = false;
|
||||||
|
this.dragStartX = this.lastClientX;
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
var onStart = function (el, event) {
|
||||||
|
if (this.canResize) {
|
||||||
|
this.currentHeaderAction = 'resize';
|
||||||
|
this.startWidth = this.resizeTh.getStyle('width').toFloat();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.currentHeaderAction = 'drag';
|
||||||
|
el.setStyle('background-color', '#C1D5E7');
|
||||||
|
}
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
var onDrag = function (el, event) {
|
||||||
|
if (this.currentHeaderAction === 'resize') {
|
||||||
|
var width = this.startWidth + (event.page.x - this.dragStartX);
|
||||||
|
if (width < 16)
|
||||||
|
width = 16;
|
||||||
|
this.columns[this.resizeTh.columnName].width = width;
|
||||||
|
this.updateColumn(this.resizeTh.columnName);
|
||||||
|
}
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
var onComplete = function (el, event) {
|
||||||
|
resetElementBorderStyle(this.lastHoverTh);
|
||||||
|
el.setStyle('background-color', '');
|
||||||
|
if (this.currentHeaderAction === 'resize')
|
||||||
|
localStorage.setItem('column_' + this.resizeTh.columnName + '_width_' + this.dynamicTableDivId, this.columns[this.resizeTh.columnName].width);
|
||||||
|
if ((this.currentHeaderAction === 'drag') && (el !== this.lastHoverTh)) {
|
||||||
|
this.saveColumnsOrder();
|
||||||
|
var val = localStorage.getItem('columns_order_' + this.dynamicTableDivId).split(',');
|
||||||
|
val.erase(el.columnName);
|
||||||
|
var pos = val.indexOf(this.lastHoverTh.columnName);
|
||||||
|
if (this.dropSide === 'right') pos++;
|
||||||
|
val.splice(pos, 0, el.columnName);
|
||||||
|
localStorage.setItem('columns_order_' + this.dynamicTableDivId, val.join(','));
|
||||||
|
this.loadColumnsOrder();
|
||||||
|
this.updateTableHeaders();
|
||||||
|
while (this.tableBody.firstChild)
|
||||||
|
this.tableBody.removeChild(this.tableBody.firstChild);
|
||||||
|
this.updateTable(true);
|
||||||
|
}
|
||||||
|
if (this.currentHeaderAction === 'drag') {
|
||||||
|
resetElementBorderStyle(el);
|
||||||
|
el.getSiblings('[class=""]').each(function(el){
|
||||||
|
resetElementBorderStyle(el);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.currentHeaderAction = '';
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
var onCancel = function (el) {
|
||||||
|
this.currentHeaderAction = '';
|
||||||
|
this.setSortedColumn(el.columnName);
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
var ths = this.fixedTableHeader.getElements('th');
|
||||||
|
|
||||||
|
for (var i = 0; i < ths.length; i++) {
|
||||||
|
var th = ths[i];
|
||||||
|
th.addEvent('mousemove', mouseMoveFn);
|
||||||
|
th.addEvent('mouseout', mouseOutFn);
|
||||||
|
th.makeResizable({
|
||||||
|
modifiers : {x: '', y: ''},
|
||||||
|
onBeforeStart : onBeforeStart,
|
||||||
|
onStart : onStart,
|
||||||
|
onDrag : onDrag,
|
||||||
|
onComplete : onComplete,
|
||||||
|
onCancel : onCancel
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setupDynamicTableHeaderContextMenuClass : function () {
|
||||||
|
if (!DynamicTableHeaderContextMenuClass) {
|
||||||
|
DynamicTableHeaderContextMenuClass = new Class({
|
||||||
|
Extends: ContextMenu,
|
||||||
|
updateMenuItems: function () {
|
||||||
|
for (var i = 0; i < this.dynamicTable.columns.length; i++) {
|
||||||
|
if (this.dynamicTable.columns[i].caption === '')
|
||||||
|
continue;
|
||||||
|
if (this.dynamicTable.columns[i].visible !== '0')
|
||||||
|
this.setItemChecked(this.dynamicTable.columns[i].name, true);
|
||||||
|
else
|
||||||
|
this.setItemChecked(this.dynamicTable.columns[i].name, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
showColumn : function (columnName, show) {
|
||||||
|
this.columns[columnName].visible = show ? '1' : '0';
|
||||||
|
localStorage.setItem('column_' + columnName + '_visible_' + this.dynamicTableDivId, show ? '1' : '0');
|
||||||
|
this.updateColumn(columnName);
|
||||||
|
},
|
||||||
|
|
||||||
|
setupHeaderMenu : function () {
|
||||||
|
this.setupDynamicTableHeaderContextMenuClass();
|
||||||
|
|
||||||
|
var menuId = this.dynamicTableDivId + '_headerMenu';
|
||||||
|
|
||||||
|
var ul = new Element('ul', {id: menuId, class: 'contextMenu scrollableMenu'});
|
||||||
|
|
||||||
|
var createLi = function(columnName, text) {
|
||||||
|
var html = '<a href="#' + columnName + '" ><img src="theme/checked"/>' + escapeHtml(text) + '</a>';
|
||||||
|
return new Element('li', {html: html});
|
||||||
|
};
|
||||||
|
|
||||||
|
var actions = {};
|
||||||
|
|
||||||
|
var onMenuItemClicked = function (element, ref, action) {
|
||||||
|
this.showColumn(action, this.columns[action].visible === '0');
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
for (var i = 0; i < this.columns.length; i++) {
|
||||||
|
var text = this.columns[i].caption;
|
||||||
|
if (text === '')
|
||||||
|
continue;
|
||||||
|
ul.appendChild(createLi(this.columns[i].name, text));
|
||||||
|
actions[this.columns[i].name] = onMenuItemClicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.inject(document.body);
|
||||||
|
|
||||||
|
this.headerContextMenu = new DynamicTableHeaderContextMenuClass({
|
||||||
|
targets: '#' + this.dynamicTableFixedHeaderDivId + ' tr',
|
||||||
|
actions: actions,
|
||||||
|
menu : menuId,
|
||||||
|
offsets : {
|
||||||
|
x : -15,
|
||||||
|
y : 2
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.headerContextMenu.dynamicTable = this;
|
||||||
},
|
},
|
||||||
|
|
||||||
initColumns : function () {},
|
initColumns : function () {},
|
||||||
|
|
||||||
newColumn : function (name, style, caption) {
|
newColumn : function (name, style, caption, defaultWidth, defaultVisible) {
|
||||||
var column = {};
|
var column = {};
|
||||||
column['name'] = name;
|
column['name'] = name;
|
||||||
column['visible'] = getLocalStorageItem('column_' + name + '_visible_' + this.tableId, '1');
|
column['visible'] = getLocalStorageItem('column_' + name + '_visible_' + this.dynamicTableDivId, defaultVisible ? '1' : '0');
|
||||||
column['force_hide'] = false;
|
column['force_hide'] = false;
|
||||||
column['caption'] = caption;
|
column['caption'] = caption;
|
||||||
column['style'] = style;
|
column['style'] = style;
|
||||||
column['onclick'] = 'this._this.setSortedColumn(\'' + name + '\');';
|
column['width'] = getLocalStorageItem('column_' + name + '_width_' + this.dynamicTableDivId, defaultWidth);
|
||||||
column['dataProperties'] = [name];
|
column['dataProperties'] = [name];
|
||||||
column['getRowValue'] = function (row, pos) {
|
column['getRowValue'] = function (row, pos) {
|
||||||
if (pos == undefined)
|
if (pos == undefined)
|
||||||
|
@ -76,15 +344,17 @@ var DynamicTable = new Class({
|
||||||
column['updateTd'] = function (td, row) {
|
column['updateTd'] = function (td, row) {
|
||||||
td.innerHTML = this.getRowValue(row);
|
td.innerHTML = this.getRowValue(row);
|
||||||
};
|
};
|
||||||
|
column['onResize'] = null;
|
||||||
this.columns.push(column);
|
this.columns.push(column);
|
||||||
this.columns[name] = column;
|
this.columns[name] = column;
|
||||||
|
|
||||||
$(this.tableHeaderId).appendChild(new Element('th'));
|
this.hiddenTableHeader.appendChild(new Element('th'));
|
||||||
|
this.fixedTableHeader.appendChild(new Element('th'));
|
||||||
},
|
},
|
||||||
|
|
||||||
loadColumnsOrder : function () {
|
loadColumnsOrder : function () {
|
||||||
columnsOrder = ['state_icon']; // status icon column is always the first
|
var columnsOrder = [];
|
||||||
val = localStorage.getItem('columns_order_' + this.tableId);
|
var val = localStorage.getItem('columns_order_' + this.dynamicTableDivId);
|
||||||
if (val === null || val === undefined) return;
|
if (val === null || val === undefined) return;
|
||||||
val.split(',').forEach(function(v) {
|
val.split(',').forEach(function(v) {
|
||||||
if ((v in this.columns) && (!columnsOrder.contains(v)))
|
if ((v in this.columns) && (!columnsOrder.contains(v)))
|
||||||
|
@ -106,18 +376,24 @@ var DynamicTable = new Class({
|
||||||
val += ',';
|
val += ',';
|
||||||
val += this.columns[i].name;
|
val += this.columns[i].name;
|
||||||
}
|
}
|
||||||
localStorage.setItem('columns_order_' + this.tableId, val);
|
localStorage.setItem('columns_order_' + this.dynamicTableDivId, val);
|
||||||
},
|
},
|
||||||
|
|
||||||
updateHeader : function () {
|
updateTableHeaders : function () {
|
||||||
var ths = $(this.tableHeaderId).getElements('th');
|
this.updateHeader(this.hiddenTableHeader);
|
||||||
|
this.updateHeader(this.fixedTableHeader);
|
||||||
|
},
|
||||||
|
|
||||||
|
updateHeader : function (header) {
|
||||||
|
var ths = header.getElements('th');
|
||||||
|
|
||||||
for (var i = 0; i < ths.length; i++) {
|
for (var i = 0; i < ths.length; i++) {
|
||||||
th = ths[i];
|
th = ths[i];
|
||||||
th._this = this;
|
th._this = this;
|
||||||
th.setAttribute('onclick', this.columns[i].onclick);
|
th.setAttribute('title', this.columns[i].caption);
|
||||||
th.innerHTML = this.columns[i].caption;
|
th.innerHTML = this.columns[i].caption;
|
||||||
th.setAttribute('style', this.columns[i].style);
|
th.setAttribute('style', 'width: ' + this.columns[i].width + 'px;' + this.columns[i].style);
|
||||||
|
th.columnName = this.columns[i].name;
|
||||||
if ((this.columns[i].visible == '0') || this.columns[i].force_hide)
|
if ((this.columns[i].visible == '0') || this.columns[i].force_hide)
|
||||||
th.addClass('invisible');
|
th.addClass('invisible');
|
||||||
else
|
else
|
||||||
|
@ -135,17 +411,30 @@ var DynamicTable = new Class({
|
||||||
updateColumn : function (columnName) {
|
updateColumn : function (columnName) {
|
||||||
var pos = this.getColumnPos(columnName);
|
var pos = this.getColumnPos(columnName);
|
||||||
var visible = ((this.columns[pos].visible != '0') && !this.columns[pos].force_hide);
|
var visible = ((this.columns[pos].visible != '0') && !this.columns[pos].force_hide);
|
||||||
var ths = $(this.tableHeaderId).getElements('th');
|
var ths = this.hiddenTableHeader.getElements('th');
|
||||||
if (visible)
|
var fths = this.fixedTableHeader.getElements('th');
|
||||||
|
var trs = this.tableBody.getElements('tr');
|
||||||
|
var style = 'width: ' + this.columns[pos].width + 'px;' + this.columns[pos].style;
|
||||||
|
|
||||||
|
ths[pos].setAttribute('style', style);
|
||||||
|
fths[pos].setAttribute('style', style);
|
||||||
|
|
||||||
|
if (visible) {
|
||||||
ths[pos].removeClass('invisible');
|
ths[pos].removeClass('invisible');
|
||||||
else
|
fths[pos].removeClass('invisible');
|
||||||
ths[pos].addClass('invisible');
|
for (var i = 0; i < trs.length; i++)
|
||||||
var trs = this.table.getElements('tr');
|
|
||||||
for (var i = 0; i < trs.length; i++)
|
|
||||||
if (visible)
|
|
||||||
trs[i].getElements('td')[pos].removeClass('invisible');
|
trs[i].getElements('td')[pos].removeClass('invisible');
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
|
ths[pos].addClass('invisible');
|
||||||
|
fths[pos].addClass('invisible');
|
||||||
|
for (var i = 0; i < trs.length; i++)
|
||||||
trs[i].getElements('td')[pos].addClass('invisible');
|
trs[i].getElements('td')[pos].addClass('invisible');
|
||||||
|
}
|
||||||
|
if (this.columns[pos].onResize !== null)
|
||||||
|
{
|
||||||
|
this.columns[pos].onResize(columnName);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setSortedColumn : function (column) {
|
setSortedColumn : function (column) {
|
||||||
|
@ -157,14 +446,14 @@ var DynamicTable = new Class({
|
||||||
// Toggle sort order
|
// Toggle sort order
|
||||||
this.reverseSort = this.reverseSort == '0' ? '1' : '0';
|
this.reverseSort = this.reverseSort == '0' ? '1' : '0';
|
||||||
}
|
}
|
||||||
localStorage.setItem('sorted_column_' + this.tableId, column);
|
localStorage.setItem('sorted_column_' + this.dynamicTableDivId, column);
|
||||||
localStorage.setItem('reverse_sort_' + this.tableId, this.reverseSort);
|
localStorage.setItem('reverse_sort_' + this.dynamicTableDivId, this.reverseSort);
|
||||||
this.updateTable(false);
|
this.updateTable(false);
|
||||||
},
|
},
|
||||||
|
|
||||||
getSelectedRowId : function () {
|
getSelectedRowId : function () {
|
||||||
if (this.cur.length > 0)
|
if (this.selectedRows.length > 0)
|
||||||
return this.cur[0];
|
return this.selectedRows[0];
|
||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -172,7 +461,7 @@ var DynamicTable = new Class({
|
||||||
if (!MUI.ieLegacySupport)
|
if (!MUI.ieLegacySupport)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var trs = this.table.getElements('tr');
|
var trs = this.tableBody.getElements('tr');
|
||||||
trs.each(function (el, i) {
|
trs.each(function (el, i) {
|
||||||
if (i % 2) {
|
if (i % 2) {
|
||||||
el.addClass('alt');
|
el.addClass('alt');
|
||||||
|
@ -183,25 +472,25 @@ var DynamicTable = new Class({
|
||||||
},
|
},
|
||||||
|
|
||||||
selectAll : function () {
|
selectAll : function () {
|
||||||
this.cur.empty();
|
this.selectedRows.empty();
|
||||||
|
|
||||||
var trs = this.table.getElements('tr');
|
var trs = this.tableBody.getElements('tr');
|
||||||
for (var i = 0; i < trs.length; i++) {
|
for (var i = 0; i < trs.length; i++) {
|
||||||
var tr = trs[i];
|
var tr = trs[i];
|
||||||
this.cur.push(tr.rowId);
|
this.selectedRows.push(tr.rowId);
|
||||||
if (!tr.hasClass('selected'))
|
if (!tr.hasClass('selected'))
|
||||||
tr.addClass('selected');
|
tr.addClass('selected');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
deselectAll : function () {
|
deselectAll : function () {
|
||||||
this.cur.empty();
|
this.selectedRows.empty();
|
||||||
},
|
},
|
||||||
|
|
||||||
selectRow : function (rowId) {
|
selectRow : function (rowId) {
|
||||||
this.cur.empty();
|
this.selectedRows.empty();
|
||||||
this.cur.push(rowId);
|
this.selectedRows.push(rowId);
|
||||||
var trs = this.table.getElements('tr');
|
var trs = this.tableBody.getElements('tr');
|
||||||
for (var i = 0; i < trs.length; i++) {
|
for (var i = 0; i < trs.length; i++) {
|
||||||
var tr = trs[i];
|
var tr = trs[i];
|
||||||
if (tr.rowId == rowId) {
|
if (tr.rowId == rowId) {
|
||||||
|
@ -259,7 +548,7 @@ var DynamicTable = new Class({
|
||||||
},
|
},
|
||||||
|
|
||||||
getTrByRowId : function (rowId) {
|
getTrByRowId : function (rowId) {
|
||||||
trs = this.table.getElements('tr');
|
trs = this.tableBody.getElements('tr');
|
||||||
for (var i = 0; i < trs.length; i++)
|
for (var i = 0; i < trs.length; i++)
|
||||||
if (trs[i].rowId == rowId)
|
if (trs[i].rowId == rowId)
|
||||||
return trs[i];
|
return trs[i];
|
||||||
|
@ -272,20 +561,19 @@ var DynamicTable = new Class({
|
||||||
|
|
||||||
var rows = this.getFilteredAndSortedRows();
|
var rows = this.getFilteredAndSortedRows();
|
||||||
|
|
||||||
for (var i = 0; i < this.cur.length; i++)
|
for (var i = 0; i < this.selectedRows.length; i++)
|
||||||
if (!(this.cur[i] in rows)) {
|
if (!(this.selectedRows[i] in rows)) {
|
||||||
this.cur.splice(i, 1);
|
this.selectedRows.splice(i, 1);
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
|
|
||||||
var trs = this.table.getElements('tr');
|
var trs = this.tableBody.getElements('tr');
|
||||||
|
|
||||||
for (var rowPos = 0; rowPos < rows.length; rowPos++) {
|
for (var rowPos = 0; rowPos < rows.length; rowPos++) {
|
||||||
var rowId = rows[rowPos]['rowId'];
|
var rowId = rows[rowPos]['rowId'];
|
||||||
tr_found = false;
|
tr_found = false;
|
||||||
for (j = rowPos; j < trs.length; j++)
|
for (j = rowPos; j < trs.length; j++)
|
||||||
if (trs[j]['rowId'] == rowId) {
|
if (trs[j]['rowId'] == rowId) {
|
||||||
trs[rowPos].removeClass('over');
|
|
||||||
tr_found = true;
|
tr_found = true;
|
||||||
if (rowPos == j)
|
if (rowPos == j)
|
||||||
break;
|
break;
|
||||||
|
@ -304,7 +592,7 @@ var DynamicTable = new Class({
|
||||||
|
|
||||||
tr._this = this;
|
tr._this = this;
|
||||||
tr.addEvent('contextmenu', function (e) {
|
tr.addEvent('contextmenu', function (e) {
|
||||||
if (!this._this.cur.contains(this.rowId))
|
if (!this._this.selectedRows.contains(this.rowId))
|
||||||
this._this.selectRow(this.rowId);
|
this._this.selectRow(this.rowId);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -312,37 +600,37 @@ var DynamicTable = new Class({
|
||||||
e.stop();
|
e.stop();
|
||||||
if (e.control) {
|
if (e.control) {
|
||||||
// CTRL key was pressed
|
// CTRL key was pressed
|
||||||
if (this._this.cur.contains(this.rowId)) {
|
if (this._this.selectedRows.contains(this.rowId)) {
|
||||||
// remove it
|
// remove it
|
||||||
this._this.cur.erase(this.rowId);
|
this._this.selectedRows.erase(this.rowId);
|
||||||
// Remove selected style
|
// Remove selected style
|
||||||
this.removeClass('selected');
|
this.removeClass('selected');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this._this.cur.push(this.rowId);
|
this._this.selectedRows.push(this.rowId);
|
||||||
// Add selected style
|
// Add selected style
|
||||||
this.addClass('selected');
|
this.addClass('selected');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (e.shift && this._this.cur.length == 1) {
|
if (e.shift && this._this.selectedRows.length == 1) {
|
||||||
// Shift key was pressed
|
// Shift key was pressed
|
||||||
var first_row_id = this._this.cur[0];
|
var first_row_id = this._this.selectedRows[0];
|
||||||
var last_row_id = this.rowId;
|
var last_row_id = this.rowId;
|
||||||
this._this.cur.empty();
|
this._this.selectedRows.empty();
|
||||||
var trs = this._this.table.getElements('tr');
|
var trs = this._this.tableBody.getElements('tr');
|
||||||
var select = false;
|
var select = false;
|
||||||
for (var i = 0; i < trs.length; i++) {
|
for (var i = 0; i < trs.length; i++) {
|
||||||
var tr = trs[i];
|
var tr = trs[i];
|
||||||
|
|
||||||
if ((tr.rowId == first_row_id) || (tr.rowId == last_row_id)) {
|
if ((tr.rowId == first_row_id) || (tr.rowId == last_row_id)) {
|
||||||
this._this.cur.push(tr.rowId);
|
this._this.selectedRows.push(tr.rowId);
|
||||||
tr.addClass('selected');
|
tr.addClass('selected');
|
||||||
select = !select;
|
select = !select;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (select) {
|
if (select) {
|
||||||
this._this.cur.push(tr.rowId);
|
this._this.selectedRows.push(tr.rowId);
|
||||||
tr.addClass('selected');
|
tr.addClass('selected');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -368,7 +656,7 @@ var DynamicTable = new Class({
|
||||||
|
|
||||||
// Insert
|
// Insert
|
||||||
if (rowPos >= trs.length) {
|
if (rowPos >= trs.length) {
|
||||||
tr.inject(this.table);
|
tr.inject(this.tableBody);
|
||||||
trs.push(tr);
|
trs.push(tr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -377,8 +665,8 @@ var DynamicTable = new Class({
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update context menu
|
// Update context menu
|
||||||
if (this.context_menu)
|
if (this.contextMenu)
|
||||||
this.context_menu.addTarget(tr);
|
this.contextMenu.addTarget(tr);
|
||||||
|
|
||||||
this.updateRow(tr, true);
|
this.updateRow(tr, true);
|
||||||
}
|
}
|
||||||
|
@ -407,7 +695,7 @@ var DynamicTable = new Class({
|
||||||
},
|
},
|
||||||
|
|
||||||
removeRow : function (rowId) {
|
removeRow : function (rowId) {
|
||||||
this.cur.erase(rowId);
|
this.selectedRows.erase(rowId);
|
||||||
var tr = this.getTrByRowId(rowId);
|
var tr = this.getTrByRowId(rowId);
|
||||||
if (tr != null) {
|
if (tr != null) {
|
||||||
tr.dispose();
|
tr.dispose();
|
||||||
|
@ -418,9 +706,9 @@ var DynamicTable = new Class({
|
||||||
},
|
},
|
||||||
|
|
||||||
clear : function () {
|
clear : function () {
|
||||||
this.cur.empty();
|
this.selectedRows.empty();
|
||||||
this.rows.empty();
|
this.rows.empty();
|
||||||
var trs = this.table.getElements('tr');
|
var trs = this.tableBody.getElements('tr');
|
||||||
while (trs.length > 0) {
|
while (trs.length > 0) {
|
||||||
trs[trs.length - 1].dispose();
|
trs[trs.length - 1].dispose();
|
||||||
trs.pop();
|
trs.pop();
|
||||||
|
@ -428,7 +716,7 @@ var DynamicTable = new Class({
|
||||||
},
|
},
|
||||||
|
|
||||||
selectedRowsIds : function () {
|
selectedRowsIds : function () {
|
||||||
return this.cur.slice();
|
return this.selectedRows.slice();
|
||||||
},
|
},
|
||||||
|
|
||||||
getRowIds : function () {
|
getRowIds : function () {
|
||||||
|
@ -440,19 +728,34 @@ var TorrentsTable = new Class({
|
||||||
Extends: DynamicTable,
|
Extends: DynamicTable,
|
||||||
|
|
||||||
initColumns : function () {
|
initColumns : function () {
|
||||||
this.newColumn('priority', 'width: 30px', '#');
|
this.newColumn('priority', '', '#', 30, true);
|
||||||
this.newColumn('state_icon', 'width: 16px; cursor: default', '');
|
this.newColumn('state_icon', 'cursor: default', '', 22, true);
|
||||||
this.newColumn('name', 'min-width: 200px', 'QBT_TR(Name)QBT_TR');
|
this.newColumn('name', '', 'QBT_TR(Name)QBT_TR[CONTEXT=TorrentModel]', 200, true);
|
||||||
this.newColumn('size', 'width: 100px', 'QBT_TR(Size)QBT_TR');
|
this.newColumn('size', '', 'QBT_TR(Size)QBT_TR[CONTEXT=TorrentModel]', 100, true);
|
||||||
this.newColumn('progress', 'width: 80px', 'QBT_TR(Done)QBT_TR');
|
this.newColumn('progress', '', 'QBT_TR(Done)QBT_TR[CONTEXT=TorrentModel]', 85, true);
|
||||||
this.newColumn('num_seeds', 'width: 100px', 'QBT_TR(Seeds)QBT_TR');
|
this.newColumn('num_seeds', '', 'QBT_TR(Seeds)QBT_TR[CONTEXT=TorrentModel]', 100, true);
|
||||||
this.newColumn('num_leechs', 'width: 100px', 'QBT_TR(Peers)QBT_TR');
|
this.newColumn('num_leechs', '', 'QBT_TR(Peers)QBT_TR[CONTEXT=TorrentModel]', 100, true);
|
||||||
this.newColumn('dlspeed', 'width: 100px', 'QBT_TR(Down Speed)QBT_TR');
|
this.newColumn('dlspeed', '', 'QBT_TR(Down Speed)QBT_TR[CONTEXT=TorrentModel]', 100, true);
|
||||||
this.newColumn('upspeed', 'width: 100px', 'QBT_TR(Up Speed)QBT_TR');
|
this.newColumn('upspeed', '', 'QBT_TR(Up Speed)QBT_TR[CONTEXT=TorrentModel]', 100, true);
|
||||||
this.newColumn('eta', 'width: 100px', 'QBT_TR(ETA)QBT_TR');
|
this.newColumn('eta', '', 'QBT_TR(ETA)QBT_TR[CONTEXT=TorrentModel]', 100, true);
|
||||||
this.newColumn('ratio', 'width: 100px', 'QBT_TR(Ratio)QBT_TR');
|
this.newColumn('ratio', '', 'QBT_TR(Ratio)QBT_TR[CONTEXT=TorrentModel]', 100, true);
|
||||||
this.newColumn('category', 'width: 100px', 'QBT_TR(Category)QBT_TR');
|
this.newColumn('category', '', 'QBT_TR(Category)QBT_TR[CONTEXT=TorrentModel]', 100, true);
|
||||||
this.newColumn('added_on', 'width: 100px', 'QBT_TR(Added on)QBT_TR');
|
this.newColumn('added_on', '', 'QBT_TR(Added On)QBT_TR[CONTEXT=TorrentModel]', 100, true);
|
||||||
|
this.newColumn('completion_on', '', 'QBT_TR(Completed On)QBT_TR[CONTEXT=TorrentModel]', 100, false);
|
||||||
|
this.newColumn('tracker', '', 'QBT_TR(Tracker)QBT_TR[CONTEXT=TorrentModel]', 100, false);
|
||||||
|
this.newColumn('dl_limit', '', 'QBT_TR(Down Limit)QBT_TR[CONTEXT=TorrentModel]', 100, false);
|
||||||
|
this.newColumn('up_limit', '', 'QBT_TR(Up Limit)QBT_TR[CONTEXT=TorrentModel]', 100, false);
|
||||||
|
this.newColumn('downloaded', '', 'QBT_TR(Downloaded)QBT_TR[CONTEXT=TorrentModel]', 100, false);
|
||||||
|
this.newColumn('uploaded', '', 'QBT_TR(Uploaded)QBT_TR[CONTEXT=TorrentModel]', 100, false);
|
||||||
|
this.newColumn('downloaded_session', '', 'QBT_TR(Session Download)QBT_TR[CONTEXT=TorrentModel]', 100, false);
|
||||||
|
this.newColumn('uploaded_session', '', 'QBT_TR(Session Upload)QBT_TR[CONTEXT=TorrentModel]', 100, false);
|
||||||
|
this.newColumn('amount_left', '', 'QBT_TR(Remaining)QBT_TR[CONTEXT=TorrentModel]', 100, false);
|
||||||
|
this.newColumn('save_path', '', 'QBT_TR(Save path)QBT_TR[CONTEXT=TorrentModel]', 100, false);
|
||||||
|
this.newColumn('completed', '', 'QBT_TR(Completed)QBT_TR[CONTEXT=TorrentModel]', 100, false);
|
||||||
|
this.newColumn('ratio_limit', '', 'QBT_TR(Ratio Limit)QBT_TR[CONTEXT=TorrentModel]', 100, false);
|
||||||
|
this.newColumn('seen_complete', '', 'QBT_TR(Last Seen Complete)QBT_TR[CONTEXT=TorrentModel]', 100, false);
|
||||||
|
this.newColumn('last_activity', '', 'QBT_TR(Last Activity)QBT_TR[CONTEXT=TorrentModel]', 100, false);
|
||||||
|
this.newColumn('total_size', '', 'QBT_TR(Total Size)QBT_TR[CONTEXT=TorrentModel]', 100, false);
|
||||||
|
|
||||||
this.columns['state_icon'].onclick = '';
|
this.columns['state_icon'].onclick = '';
|
||||||
this.columns['state_icon'].dataProperties[0] = 'state';
|
this.columns['state_icon'].dataProperties[0] = 'state';
|
||||||
|
@ -548,15 +851,27 @@ var TorrentsTable = new Class({
|
||||||
|
|
||||||
if (td.getChildren('div').length) {
|
if (td.getChildren('div').length) {
|
||||||
var div = td.getChildren('div')[0];
|
var div = td.getChildren('div')[0];
|
||||||
|
var newWidth = td.offsetWidth - 5;
|
||||||
|
if (div.lastWidth !== newWidth) {
|
||||||
|
div.setWidth(newWidth);
|
||||||
|
div.lastWidth = newWidth;
|
||||||
|
}
|
||||||
if (div.getValue() != progressFormated)
|
if (div.getValue() != progressFormated)
|
||||||
div.setValue(progressFormated);
|
div.setValue(progressFormated);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
td.adopt(new ProgressBar(progressFormated.toFloat(), {
|
td.adopt(new ProgressBar(progressFormated.toFloat(), {
|
||||||
'width' : 80
|
'width' : td.offsetWidth - 5
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.columns['progress'].onResize = function (columnName) {
|
||||||
|
var pos = this.getColumnPos(columnName);
|
||||||
|
var trs = this.tableBody.getElements('tr');
|
||||||
|
for (var i = 0; i < trs.length; i++)
|
||||||
|
this.columns[columnName].updateTd(trs[i].getElements('td')[pos], this.rows.get(trs[i].rowId));
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
// num_seeds
|
// num_seeds
|
||||||
|
|
||||||
this.columns['num_seeds'].updateTd = function (td, row) {
|
this.columns['num_seeds'].updateTd = function (td, row) {
|
||||||
|
@ -626,6 +941,64 @@ var TorrentsTable = new Class({
|
||||||
var date = new Date(this.getRowValue(row) * 1000).toLocaleString();
|
var date = new Date(this.getRowValue(row) * 1000).toLocaleString();
|
||||||
td.set('html', date);
|
td.set('html', date);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// completion_on
|
||||||
|
|
||||||
|
this.columns['completion_on'].updateTd = function (td, row) {
|
||||||
|
var val = this.getRowValue(row);
|
||||||
|
if (val === 0xffffffff || val < 0)
|
||||||
|
td.set('html', '');
|
||||||
|
else {
|
||||||
|
var date = new Date(this.getRowValue(row) * 1000).toLocaleString();
|
||||||
|
td.set('html', date);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// seen_complete
|
||||||
|
|
||||||
|
this.columns['seen_complete'].updateTd = this.columns['completion_on'].updateTd;
|
||||||
|
|
||||||
|
// dl_limit, up_limit
|
||||||
|
|
||||||
|
this.columns['dl_limit'].updateTd = function (td, row) {
|
||||||
|
var speed = this.getRowValue(row);
|
||||||
|
if (speed === 0)
|
||||||
|
td.set('html', '∞')
|
||||||
|
else
|
||||||
|
td.set('html', friendlyUnit(speed, true));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.columns['up_limit'].updateTd = this.columns['dl_limit'].updateTd;
|
||||||
|
|
||||||
|
// downloaded, uploaded, downloaded_session, uploaded_session, amount_left, completed, total_size
|
||||||
|
|
||||||
|
this.columns['downloaded'].updateTd = this.columns['size'].updateTd;
|
||||||
|
this.columns['uploaded'].updateTd = this.columns['size'].updateTd;
|
||||||
|
this.columns['downloaded_session'].updateTd = this.columns['size'].updateTd;
|
||||||
|
this.columns['uploaded_session'].updateTd = this.columns['size'].updateTd;
|
||||||
|
this.columns['amount_left'].updateTd = this.columns['size'].updateTd;
|
||||||
|
this.columns['amount_left'].updateTd = this.columns['size'].updateTd;
|
||||||
|
this.columns['completed'].updateTd = this.columns['size'].updateTd;
|
||||||
|
this.columns['total_size'].updateTd = this.columns['size'].updateTd;
|
||||||
|
|
||||||
|
// save_path, tracker
|
||||||
|
|
||||||
|
this.columns['save_path'].updateTd = this.columns['name'].updateTd;
|
||||||
|
this.columns['tracker'].updateTd = this.columns['name'].updateTd;
|
||||||
|
|
||||||
|
// ratio_limit
|
||||||
|
|
||||||
|
this.columns['ratio_limit'].updateTd = this.columns['ratio'].updateTd;
|
||||||
|
|
||||||
|
// last_activity
|
||||||
|
|
||||||
|
this.columns['last_activity'].updateTd = function (td, row) {
|
||||||
|
var val = this.getRowValue(row);
|
||||||
|
if (val < 1)
|
||||||
|
td.set('html', '∞');
|
||||||
|
else
|
||||||
|
td.set('html', 'QBT_TR(%1 ago)QBT_TR[CONTEXT=TransferListDelegate]'.replace('%1', friendlyDuration((new Date()) / 1000 - val, true)));
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
applyFilter : function (row, filterName, categoryHash) {
|
applyFilter : function (row, filterName, categoryHash) {
|
||||||
|
@ -752,18 +1125,19 @@ var TorrentPeersTable = new Class({
|
||||||
Extends: DynamicTable,
|
Extends: DynamicTable,
|
||||||
|
|
||||||
initColumns : function () {
|
initColumns : function () {
|
||||||
this.newColumn('country', 'width: 4px', '');
|
this.newColumn('country', '', 'QBT_TR(Country)QBT_TR[CONTEXT=PeerListWidget]', 22, true);
|
||||||
this.newColumn('ip', 'width: 80px', 'QBT_TR(IP)QBT_TR');
|
this.newColumn('ip', '', 'QBT_TR(IP)QBT_TR[CONTEXT=PeerListWidget]', 80, true);
|
||||||
this.newColumn('port', 'width: 35px', 'QBT_TR(Port)QBT_TR');
|
this.newColumn('port', '', 'QBT_TR(Port)QBT_TR[CONTEXT=PeerListWidget]', 35, true);
|
||||||
this.newColumn('client', 'width: 110px', 'QBT_TR(Client)QBT_TR');
|
this.newColumn('client', '', 'QBT_TR(Client)QBT_TR[CONTEXT=PeerListWidget]', 140, true);
|
||||||
this.newColumn('progress', 'width: 30px', 'QBT_TR(Progress)QBT_TR');
|
this.newColumn('progress', '', 'QBT_TR(Progress)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
|
||||||
this.newColumn('dl_speed', 'width: 30px', 'QBT_TR(Down Speed)QBT_TR');
|
this.newColumn('dl_speed', '', 'QBT_TR(Down Speed)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
|
||||||
this.newColumn('up_speed', 'width: 30px', 'QBT_TR(Up Speed)QBT_TR');
|
this.newColumn('up_speed', '', 'QBT_TR(Up Speed)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
|
||||||
this.newColumn('downloaded', 'width: 30px', 'QBT_TR(Downloaded)QBT_TR[CONTEXT=PeerListWidget]');
|
this.newColumn('downloaded', '', 'QBT_TR(Downloaded)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
|
||||||
this.newColumn('uploaded', 'width: 30px', 'QBT_TR(Uploaded)QBT_TR[CONTEXT=PeerListWidget]');
|
this.newColumn('uploaded', '', 'QBT_TR(Uploaded)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
|
||||||
this.newColumn('connection', 'width: 30px', 'QBT_TR(Connection)QBT_TR');
|
this.newColumn('connection', '', 'QBT_TR(Connection)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
|
||||||
this.newColumn('flags', 'width: 30px', 'QBT_TR(Flags)QBT_TR');
|
this.newColumn('flags', '', 'QBT_TR(Flags)QBT_TR[CONTEXT=PeerListWidget]', 50, true);
|
||||||
this.newColumn('relevance', 'min-width: 30px', 'QBT_TR(Relevance)QBT_TR');
|
this.newColumn('relevance', '', 'QBT_TR(Relevance)QBT_TR[CONTEXT=PeerListWidget]', 30, true);
|
||||||
|
this.newColumn('files', '', 'QBT_TR(Files)QBT_TR[CONTEXT=PeerListWidget]', 100, true);
|
||||||
|
|
||||||
this.columns['country'].dataProperties.push('country_code');
|
this.columns['country'].dataProperties.push('country_code');
|
||||||
this.columns['flags'].dataProperties.push('flags_desc');
|
this.columns['flags'].dataProperties.push('flags_desc');
|
||||||
|
@ -858,6 +1232,13 @@ var TorrentPeersTable = new Class({
|
||||||
td.title = this.getRowValue(row, 1);
|
td.title = this.getRowValue(row, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// files
|
||||||
|
|
||||||
|
this.columns['files'].updateTd = function (td, row) {
|
||||||
|
td.innerHTML = escapeHtml(this.getRowValue(row, 0).replace('\n', ';'));
|
||||||
|
td.title = escapeHtml(this.getRowValue(row, 0));
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,99 +1,110 @@
|
||||||
var ProgressBar = new Class({
|
var ProgressBar = new Class({
|
||||||
initialize: function(value, parameters) {
|
initialize: function(value, parameters) {
|
||||||
var vals = {
|
var vals = {
|
||||||
'id': 'progressbar_' + (ProgressBars++),
|
'id': 'progressbar_' + (ProgressBars++),
|
||||||
'value': $pick(value, 0),
|
'value': $pick(value, 0),
|
||||||
'width': 0,
|
'width': 0,
|
||||||
'height': 0,
|
'height': 0,
|
||||||
'darkbg': '#006',
|
'darkbg': '#006',
|
||||||
'darkfg': '#fff',
|
'darkfg': '#fff',
|
||||||
'lightbg': '#fff',
|
'lightbg': '#fff',
|
||||||
'lightfg': '#000'
|
'lightfg': '#000'
|
||||||
};
|
};
|
||||||
if (parameters && $type(parameters) == 'object') $extend(vals, parameters);
|
if (parameters && $type(parameters) == 'object') $extend(vals, parameters);
|
||||||
if (vals.height < 12) vals.height = 12;
|
if (vals.height < 12) vals.height = 12;
|
||||||
var obj = new Element('div', {
|
var obj = new Element('div', {
|
||||||
'id': vals.id,
|
'id': vals.id,
|
||||||
'class': 'progressbar_wrapper',
|
'class': 'progressbar_wrapper',
|
||||||
'styles': {
|
'styles': {
|
||||||
'border': '1px solid #000',
|
'border': '1px solid #000',
|
||||||
'width': vals.width,
|
'width': vals.width,
|
||||||
'height': vals.height,
|
'height': vals.height,
|
||||||
'position': 'relative',
|
'position': 'relative',
|
||||||
'margin': '0 auto'
|
'margin': '0 auto'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
obj.vals = vals;
|
obj.vals = vals;
|
||||||
obj.vals.value = $pick(value, 0); // Fix by Chris
|
obj.vals.value = $pick(value, 0); // Fix by Chris
|
||||||
obj.vals.dark = new Element('div', {
|
obj.vals.dark = new Element('div', {
|
||||||
'id': vals.id + '_dark',
|
'id': vals.id + '_dark',
|
||||||
'class': 'progressbar_dark',
|
'class': 'progressbar_dark',
|
||||||
'styles': {
|
'styles': {
|
||||||
'width': vals.width,
|
'width': vals.width,
|
||||||
'height': vals.height,
|
'height': vals.height,
|
||||||
'background': vals.darkbg,
|
'background': vals.darkbg,
|
||||||
'color': vals.darkfg,
|
'color': vals.darkfg,
|
||||||
'position': 'absolute',
|
'position': 'absolute',
|
||||||
'text-align': 'center',
|
'text-align': 'center',
|
||||||
'left': 0,
|
'left': 0,
|
||||||
'top': 0,
|
'top': 0,
|
||||||
'line-height': vals.height
|
'line-height': vals.height
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
obj.vals.light = new Element('div', {
|
obj.vals.light = new Element('div', {
|
||||||
'id': vals.id + '_light',
|
'id': vals.id + '_light',
|
||||||
'class': 'progressbar_light',
|
'class': 'progressbar_light',
|
||||||
'styles': {
|
'styles': {
|
||||||
'width': vals.width,
|
'width': vals.width,
|
||||||
'height': vals.height,
|
'height': vals.height,
|
||||||
'background': vals.lightbg,
|
'background': vals.lightbg,
|
||||||
'color': vals.lightfg,
|
'color': vals.lightfg,
|
||||||
'position': 'absolute',
|
'position': 'absolute',
|
||||||
'text-align': 'center',
|
'text-align': 'center',
|
||||||
'left': 0,
|
'left': 0,
|
||||||
'top': 0,
|
'top': 0,
|
||||||
'line-height': vals.height
|
'line-height': vals.height
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
obj.appendChild(obj.vals.dark);
|
obj.appendChild(obj.vals.dark);
|
||||||
obj.appendChild(obj.vals.light);
|
obj.appendChild(obj.vals.light);
|
||||||
obj.getValue = ProgressBar_getValue;
|
obj.getValue = ProgressBar_getValue;
|
||||||
obj.setValue = ProgressBar_setValue;
|
obj.setValue = ProgressBar_setValue;
|
||||||
if (vals.width) obj.setValue(vals.value);
|
obj.setWidth = ProgressBar_setWidth;
|
||||||
else setTimeout('ProgressBar_checkForParent("' + obj.id + '")', 1);
|
if (vals.width) obj.setValue(vals.value);
|
||||||
return obj;
|
else setTimeout('ProgressBar_checkForParent("' + obj.id + '")', 1);
|
||||||
}
|
return obj;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function ProgressBar_getValue() {
|
function ProgressBar_getValue() {
|
||||||
return this.vals.value;
|
return this.vals.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ProgressBar_setValue(value) {
|
function ProgressBar_setValue(value) {
|
||||||
value = parseFloat(value);
|
value = parseFloat(value);
|
||||||
if (isNaN(value)) value = 0;
|
if (isNaN(value)) value = 0;
|
||||||
if (value > 100) value = 100;
|
if (value > 100) value = 100;
|
||||||
if (value < 0) value = 0;
|
if (value < 0) value = 0;
|
||||||
this.vals.value = value;
|
this.vals.value = value;
|
||||||
this.vals.dark.empty();
|
this.vals.dark.empty();
|
||||||
this.vals.light.empty();
|
this.vals.light.empty();
|
||||||
this.vals.dark.appendText(value + '%');
|
this.vals.dark.appendText(value + '%');
|
||||||
this.vals.light.appendText(value + '%');
|
this.vals.light.appendText(value + '%');
|
||||||
var r = parseInt(this.vals.width * (value / 100));
|
var r = parseInt(this.vals.width * (value / 100));
|
||||||
this.vals.dark.setStyle('clip', 'rect(0,' + r + 'px,' + this.vals.height + 'px,0)');
|
this.vals.dark.setStyle('clip', 'rect(0,' + r + 'px,' + this.vals.height + 'px,0)');
|
||||||
this.vals.light.setStyle('clip', 'rect(0,' + this.vals.width + 'px,' + this.vals.height + 'px,' + r + 'px)');
|
this.vals.light.setStyle('clip', 'rect(0,' + this.vals.width + 'px,' + this.vals.height + 'px,' + r + 'px)');
|
||||||
|
}
|
||||||
|
|
||||||
|
function ProgressBar_setWidth(value) {
|
||||||
|
if (this.vals.width !== value) {
|
||||||
|
this.vals.width = value;
|
||||||
|
this.setStyle('width', value);
|
||||||
|
this.vals.dark.setStyle('width', value);
|
||||||
|
this.vals.light.setStyle('width', value);
|
||||||
|
this.setValue(this.vals.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function ProgressBar_checkForParent(id) {
|
function ProgressBar_checkForParent(id) {
|
||||||
var obj = $(id);
|
var obj = $(id);
|
||||||
if (!obj) return;
|
if (!obj) return;
|
||||||
if (!obj.parentNode) return setTimeout('ProgressBar_checkForParent("' + id + '")', 1);
|
if (!obj.parentNode) return setTimeout('ProgressBar_checkForParent("' + id + '")', 1);
|
||||||
obj.setStyle('width', '100%');
|
obj.setStyle('width', '100%');
|
||||||
var w = obj.offsetWidth;
|
var w = obj.offsetWidth;
|
||||||
obj.vals.dark.setStyle('width', w);
|
obj.vals.dark.setStyle('width', w);
|
||||||
obj.vals.light.setStyle('width', w);
|
obj.vals.light.setStyle('width', w);
|
||||||
obj.vals.width = w;
|
obj.vals.width = w;
|
||||||
obj.setValue(obj.vals.value);
|
obj.setValue(obj.vals.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
var ProgressBars = 0;
|
var ProgressBars = 0;
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
<table class="torrentTable" cellpadding="0" cellspacing="0">
|
<div id="torrentsTableFixedHeaderDiv" class="dynamicTableFixedHeaderDiv">
|
||||||
<thead>
|
<table class="dynamicTable unselectable" style="position:relative;">
|
||||||
<tr id="torrentsTableHeader" class="dynamicTableHeader">
|
<thead>
|
||||||
</tr>
|
<tr class="dynamicTableHeader"></tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="torrentsTable"></tbody>
|
</table>
|
||||||
</table>
|
</div>
|
||||||
|
|
||||||
|
<div id="torrentsTableDiv" class="dynamicTableDiv">
|
||||||
|
<table class="dynamicTable unselectable">
|
||||||
|
<thead>
|
||||||
|
<tr class="dynamicTableHeader"></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
@ -62,5 +71,5 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
torrentsTable.setup('torrentsTable', 'torrentsTableHeader', torrentsTableContextMenu);
|
torrentsTable.setup('torrentsTableDiv', 'torrentsTableFixedHeaderDiv', torrentsTableContextMenu);
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in a new issue