diff --git a/src/qtlibtorrent/qtorrenthandle.cpp b/src/qtlibtorrent/qtorrenthandle.cpp index 62b03ce5c..d30d0cacc 100644 --- a/src/qtlibtorrent/qtorrenthandle.cpp +++ b/src/qtlibtorrent/qtorrenthandle.cpp @@ -489,6 +489,22 @@ qulonglong QTorrentHandle::eta() const return QBtSession::instance()->getETA(hash(), s); } +void QTorrentHandle::toggleSequentialDownload() +{ + if (is_valid() && has_metadata()) { + bool was_sequential = is_sequential_download(); + set_sequential_download(!was_sequential); + if (!was_sequential) + prioritize_first_last_piece(true); + } +} + +void QTorrentHandle::toggleFirstLastPiecePrio() +{ + if (is_valid() && has_metadata()) + prioritize_first_last_piece(!first_last_piece_first()); +} + // // Setters // diff --git a/src/qtlibtorrent/qtorrenthandle.h b/src/qtlibtorrent/qtorrenthandle.h index a36593ba5..9fc1e7364 100644 --- a/src/qtlibtorrent/qtorrenthandle.h +++ b/src/qtlibtorrent/qtorrenthandle.h @@ -128,6 +128,8 @@ public: void file_progress(std::vector& fp) const; QTorrentState torrentState() const; qulonglong eta() const; + void toggleSequentialDownload(); + void toggleFirstLastPiecePrio(); // // Setters diff --git a/src/transferlistwidget.cpp b/src/transferlistwidget.cpp index 382e76359..81109f489 100644 --- a/src/transferlistwidget.cpp +++ b/src/transferlistwidget.cpp @@ -610,12 +610,7 @@ void TransferListWidget::toggleSelectedTorrentsSequentialDownload() const const QStringList hashes = getSelectedTorrentsHashes(); foreach (const QString &hash, hashes) { QTorrentHandle h = BTSession->getTorrentHandle(hash); - if (h.is_valid() && h.has_metadata()) { - bool was_sequential = h.is_sequential_download(); - h.set_sequential_download(!was_sequential); - if (!was_sequential) - h.prioritize_first_last_piece(true); - } + h.toggleSequentialDownload(); } } @@ -624,8 +619,7 @@ void TransferListWidget::toggleSelectedFirstLastPiecePrio() const QStringList hashes = getSelectedTorrentsHashes(); foreach (const QString &hash, hashes) { QTorrentHandle h = BTSession->getTorrentHandle(hash); - if (h.is_valid() && h.has_metadata()) - h.prioritize_first_last_piece(!h.first_last_piece_first()); + h.toggleFirstLastPiecePrio(); } } diff --git a/src/webui/btjson.cpp b/src/webui/btjson.cpp index 72878b7ba..0f422b4ad 100644 --- a/src/webui/btjson.cpp +++ b/src/webui/btjson.cpp @@ -98,6 +98,8 @@ static const char KEY_TORRENT_NUM_INCOMPLETE[] = "num_incomplete"; static const char KEY_TORRENT_RATIO[] = "ratio"; static const char KEY_TORRENT_ETA[] = "eta"; static const char KEY_TORRENT_STATE[] = "state"; +static const char KEY_TORRENT_SEQUENTIAL_DOWNLOAD[] = "seq_dl"; +static const char KEY_TORRENT_FIRST_LAST_PIECE_PRIO[] = "f_l_piece_prio"; // Tracker keys static const char KEY_TRACKER_URL[] = "url"; @@ -211,6 +213,12 @@ static QVariantMap toMap(const QTorrentHandle& h) ret[KEY_TORRENT_RATIO] = (ratio > 100.) ? -1 : ratio; ret[KEY_TORRENT_STATE] = h.torrentState().toString(); ret[KEY_TORRENT_ETA] = h.eta(); + if (h.has_metadata()) { + if (status.sequential_download) + ret[KEY_TORRENT_SEQUENTIAL_DOWNLOAD] = true; + if (h.first_last_piece_first()) + ret[KEY_TORRENT_FIRST_LAST_PIECE_PRIO] = true; + } return ret; } diff --git a/src/webui/requesthandler.cpp b/src/webui/requesthandler.cpp index 3b56c6daf..0276dbf4b 100644 --- a/src/webui/requesthandler.cpp +++ b/src/webui/requesthandler.cpp @@ -100,6 +100,8 @@ QMap > RequestHandler::initialize ADD_ACTION(command, getTorrentDlLimit); ADD_ACTION(command, setTorrentUpLimit); ADD_ACTION(command, setTorrentDlLimit); + ADD_ACTION(command, toggleSequentialDownload); + ADD_ACTION(command, toggleFirstLastPiecePrio); ADD_ACTION(command, delete); ADD_ACTION(command, deletePerm); ADD_ACTION(command, increasePrio); @@ -426,6 +428,30 @@ void RequestHandler::action_command_setTorrentDlLimit() h.set_download_limit(limit); } +void RequestHandler::action_command_toggleSequentialDownload() +{ + QStringList hashes = request().posts["hashes"].split("|"); + foreach (const QString &hash, hashes) { + try { + QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); + h.toggleSequentialDownload(); + } + catch(invalid_handle&) {} + } +} + +void RequestHandler::action_command_toggleFirstLastPiecePrio() +{ + QStringList hashes = request().posts["hashes"].split("|"); + foreach (const QString &hash, hashes) { + try { + QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); + h.toggleFirstLastPiecePrio(); + } + catch(invalid_handle&) {} + } +} + void RequestHandler::action_command_delete() { QStringList hashes = request().posts["hashes"].split("|"); diff --git a/src/webui/requesthandler.h b/src/webui/requesthandler.h index f1d019999..ec34385e1 100644 --- a/src/webui/requesthandler.h +++ b/src/webui/requesthandler.h @@ -74,6 +74,8 @@ private: void action_command_getTorrentDlLimit(); void action_command_setTorrentUpLimit(); void action_command_setTorrentDlLimit(); + void action_command_toggleSequentialDownload(); + void action_command_toggleFirstLastPiecePrio(); void action_command_delete(); void action_command_deletePerm(); void action_command_increasePrio(); diff --git a/src/webui/www/private/index.html b/src/webui/www/private/index.html index 631cbddf2..4737eae1e 100644 --- a/src/webui/www/private/index.html +++ b/src/webui/www/private/index.html @@ -109,6 +109,8 @@
  • _(Limit download rate...) _(Limit download rate...)
  • _(Limit upload rate...) _(Limit upload rate...)
  • +
  • _(Download in sequential order) _(Download in sequential order)
  • +
  • _(Download first and last piece first) _(Download first and last piece first)
  • _(Force recheck) _(Force recheck)
  • diff --git a/src/webui/www/public/scripts/client.js b/src/webui/www/public/scripts/client.js index 9a4f7b9ba..d7aaa527a 100644 --- a/src/webui/www/public/scripts/client.js +++ b/src/webui/www/public/scripts/client.js @@ -99,14 +99,21 @@ var loadTorrentsInfo = function () { data[10] = event.ratio; if (row[2] != null) queueing_enabled = true; + + attrs = {}; + attrs['downloaded'] = (event.progress == 1.0); + attrs['state'] = event.state; + attrs['seq_dl'] = (event.seq_dl == true); + attrs['f_l_piece_prio'] = (event.f_l_piece_prio == true); + if (!torrent_hashes.contains(event.hash)) { // New unfinished torrent torrent_hashes[torrent_hashes.length] = event.hash; //alert("Inserting row"); - myTable.insertRow(event.hash, row, data, event.state, pos); + myTable.insertRow(event.hash, row, data, attrs, pos); } else { // Update torrent data - myTable.updateRow(event.hash, row, data, event.state, pos); + myTable.updateRow(event.hash, row, data, attrs, pos); } pos++; diff --git a/src/webui/www/public/scripts/contextmenu.js b/src/webui/www/public/scripts/contextmenu.js index abe0cedff..660bfb54a 100644 --- a/src/webui/www/public/scripts/contextmenu.js +++ b/src/webui/www/public/scripts/contextmenu.js @@ -127,9 +127,36 @@ var ContextMenu = new Class({ }.bind(this)); }, + updateMenuItems: function () { + all_are_seq_dl = true; + all_are_f_l_piece_prio = true; + all_are_downloaded = true; + + var h = myTable.selectedIds(); + h.each(function(item, index){ + tr = myTable.rows.get(item); + if (tr.getAttribute('seq_dl') != 'true') + all_are_seq_dl = false; + if (tr.getAttribute('f_l_piece_prio') != 'true') + all_are_f_l_piece_prio = false; + if (tr.getAttribute('downloaded') != 'true') + all_are_downloaded = false; + }); + + if (all_are_downloaded) { + this.hideItem('SequentialDownload'); + this.hideItem('FirstLastPiecePrio'); + } else { + this.showItem('SequentialDownload'); + this.showItem('FirstLastPiecePrio'); + this.setItemChecked('SequentialDownload', all_are_seq_dl); + this.setItemChecked('FirstLastPiecePrio', all_are_f_l_piece_prio); + } + }, + //show menu show: function(trigger) { - //this.menu.fade('in'); + this.updateMenuItems(); this.fx.start(1); this.fireEvent('show'); this.shown = true; @@ -147,15 +174,21 @@ var ContextMenu = new Class({ return this; }, - //disable an item - disableItem: function(item) { - this.menu.getElements('a[href$=' + item + ']').addClass('disabled'); + setItemChecked: function(item, checked) { + this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity = + checked ? '1' : '0'; return this; }, - //enable an item - enableItem: function(item) { - this.menu.getElements('a[href$=' + item + ']').removeClass('disabled'); + //hide an item + hideItem: function(item) { + this.menu.getElement('a[href$=' + item + ']').parentNode.addClass('invisible'); + return this; + }, + + //show an item + showItem: function(item) { + this.menu.getElement('a[href$=' + item + ']').parentNode.removeClass('invisible'); return this; }, diff --git a/src/webui/www/public/scripts/dynamicTable.js b/src/webui/www/public/scripts/dynamicTable.js index 4e032b362..0c5b2a44f 100644 --- a/src/webui/www/public/scripts/dynamicTable.js +++ b/src/webui/www/public/scripts/dynamicTable.js @@ -102,11 +102,13 @@ var dynamicTable = new Class({ this.priority_hidden = false; }, - insertRow : function (id, row, data, status, pos) { + insertRow : function (id, row, data, attrs, pos) { if (this.rows.has(id)) { return; } var tr = new Element('tr'); + for (var a in attrs) + tr.set(a, attrs[a]); tr.addClass("menu-target"); this.rows.set(id, tr); for (var i = 0; i < row.length; i++) { @@ -246,12 +248,14 @@ var dynamicTable = new Class({ }, this); }, - updateRow : function (id, row, data, status, newpos) { + updateRow : function (id, row, data, attrs, newpos) { if (!this.rows.has(id)) { return false; } var tr = this.rows.get(id); + for (var a in attrs) + tr.set(a, attrs[a]); var tds = tr.getElements('td'); for (var i = 0; i < row.length; i++) { if (i == 1) diff --git a/src/webui/www/public/scripts/mocha-init.js b/src/webui/www/public/scripts/mocha-init.js index 651bf19eb..1fe3791f7 100644 --- a/src/webui/www/public/scripts/mocha-init.js +++ b/src/webui/www/public/scripts/mocha-init.js @@ -134,6 +134,34 @@ initializeWindows = function() { } }; + toggleSequentialDownloadFN = function() { + var h = myTable.selectedIds(); + if (h.length) { + new Request({ + url: 'command/toggleSequentialDownload', + method: 'post', + data: { + hashes: h.join("|") + } + }).send(); + updateTransferList(); + } + }; + + toggleFirstLastPiecePrioFN = function() { + var h = myTable.selectedIds(); + if (h.length) { + new Request({ + url: 'command/toggleFirstLastPiecePrio', + method: 'post', + data: { + hashes: h.join("|") + } + }).send(); + updateTransferList(); + } + }; + globalDownloadLimitFN = function() { new MochaUI.Window({ id: 'downloadLimitPage', diff --git a/src/webui/www/public/transferlist.html b/src/webui/www/public/transferlist.html index 8cfa98680..1891a11f4 100644 --- a/src/webui/www/public/transferlist.html +++ b/src/webui/www/public/transferlist.html @@ -52,11 +52,17 @@ ForceRecheck : function (element, ref) { recheckFN(); }, - UploadLimit : function (element, red) { + UploadLimit : function (element, ref) { uploadLimitFN(); }, - DownloadLimit : function (element, red) { + DownloadLimit : function (element, ref) { downloadLimitFN(); + }, + SequentialDownload : function (element, ref) { + toggleSequentialDownloadFN(); + }, + FirstLastPiecePrio : function (element, ref) { + toggleFirstLastPiecePrioFN(); } }, offsets : {