mirror of
https://git.deluge-torrent.org/deluge
synced 2025-08-02 22:48:40 +00:00
pieces rewrite - micah
This commit is contained in:
parent
f0b3293dad
commit
2fa11dc18f
3 changed files with 292 additions and 241 deletions
|
@ -18,25 +18,19 @@
|
||||||
|
|
||||||
plugin_name = _("Torrent Pieces")
|
plugin_name = _("Torrent Pieces")
|
||||||
plugin_author = "Micah Bucy"
|
plugin_author = "Micah Bucy"
|
||||||
plugin_version = "0.2"
|
plugin_version = "0.3"
|
||||||
plugin_description = _("""
|
plugin_description = _("""
|
||||||
Adds a pieces tab which gives piece by piece progress for a torrent.
|
Pieces tab now shows percentage instead
|
||||||
Each piece is represented by a small progress bar.
|
of progress bars. There are no longer any tooltips.
|
||||||
|
Peer speed uses following symbols:
|
||||||
|
fast is +
|
||||||
|
medium is =
|
||||||
|
slow is -
|
||||||
|
|
||||||
Pieces currently downloading show up as partially filled progress bars,
|
monospace font is required for columns to be aligned.
|
||||||
but this does not represent percentage done.
|
|
||||||
|
|
||||||
More information is provided as a tooltip for each piece.
|
Finished torrents do not show piece information, just
|
||||||
For currently downloading pieces, the tooltip contains the number
|
a message that the torrent is complete.
|
||||||
of blocks finished as well as the peer speed for that piece.
|
|
||||||
|
|
||||||
When the plugin initializes, such as when enabling the plugin or
|
|
||||||
when a different torrent is selected, the cpu will spike. This is normal,
|
|
||||||
as initialization must get information on every piece from libtorrent,
|
|
||||||
and the cpu will normalize once all of the information is retrieved.
|
|
||||||
|
|
||||||
This plugin supports multifile torrents. If a file is skipped, it does not
|
|
||||||
show up in the pieces tab.
|
|
||||||
""")
|
""")
|
||||||
|
|
||||||
def deluge_init(deluge_path):
|
def deluge_init(deluge_path):
|
||||||
|
@ -58,24 +52,74 @@ class TorrentPieces:
|
||||||
print "Loading TorrentPieces plugin..."
|
print "Loading TorrentPieces plugin..."
|
||||||
self.manager = core
|
self.manager = core
|
||||||
self.parent = interface
|
self.parent = interface
|
||||||
scrolledWindow = gtk.ScrolledWindow()
|
self.config_file = deluge.common.CONFIG_DIR + "/pieces.conf"
|
||||||
scrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
self.config = deluge.pref.Preferences(self.config_file)
|
||||||
self.topWidget = scrolledWindow
|
try:
|
||||||
|
self.config.load()
|
||||||
|
except IOError:
|
||||||
|
# File does not exist
|
||||||
|
pass
|
||||||
|
self.glade = gtk.glade.XML(path + "/pieces_preferences.glade")
|
||||||
|
widget = self.glade.get_widget("hbox_columns")
|
||||||
|
self.combo_columns = gtk.combo_box_new_text()
|
||||||
|
for x in xrange(100):
|
||||||
|
self.combo_columns.append_text(str(x+1))
|
||||||
|
widget.pack_start(self.combo_columns, expand=False)
|
||||||
|
widget.show_all()
|
||||||
|
widget = self.glade.get_widget("hbox_font_size")
|
||||||
|
self.combo_font_size = gtk.combo_box_new_text()
|
||||||
|
for x in xrange(100):
|
||||||
|
self.combo_font_size.append_text(str(x+1))
|
||||||
|
widget.pack_start(self.combo_font_size, expand=False)
|
||||||
|
widget.show_all()
|
||||||
|
self.dialog = self.glade.get_widget("dialog")
|
||||||
|
self.glade.signal_autoconnect({
|
||||||
|
'on_button_cancel_pressed': self.cancel_pressed,
|
||||||
|
'on_button_ok_pressed': self.ok_pressed
|
||||||
|
})
|
||||||
|
scrolled_window = gtk.ScrolledWindow()
|
||||||
|
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||||
|
viewport = gtk.Viewport()
|
||||||
|
scrolled_window.add(viewport)
|
||||||
|
self.top_widget = scrolled_window
|
||||||
|
|
||||||
self.parentNotebook = self.parent.notebook
|
self.parent_notebook = self.parent.notebook
|
||||||
|
|
||||||
self.parentNotebook.append_page(self.topWidget, gtk.Label(_("Pieces")))
|
self.parent_notebook.append_page(self.top_widget, gtk.Label(_("Pieces")))
|
||||||
self.topWidget.show_all()
|
self.top_widget.show_all()
|
||||||
self.tab_pieces = PiecesTabManager(self.manager)
|
columns = self.config.get("columns")
|
||||||
|
if columns is None:
|
||||||
|
columns = 15
|
||||||
|
font_size = self.config.get("font_size")
|
||||||
|
if font_size is None:
|
||||||
|
font_size = 9
|
||||||
|
self.tab_pieces = PiecesTabManager(self.manager, viewport, columns, font_size)
|
||||||
|
self.manager.connect_event(self.manager.constants['EVENT_FINISHED'], self.handle_event)
|
||||||
|
|
||||||
def unload(self):
|
def unload(self):
|
||||||
self.tab_pieces.disconnect_handlers()
|
self.tab_pieces.disconnect_handlers()
|
||||||
|
self.manager.disconnect_event(self.manager.constants['EVENT_FINISHED'], self.handle_event)
|
||||||
self.tab_pieces.clear_pieces_store()
|
self.tab_pieces.clear_pieces_store()
|
||||||
numPages = self.parentNotebook.get_n_pages()
|
tab_page = self.parent_notebook.page_num(self.top_widget)
|
||||||
for page in xrange(numPages):
|
self.parent_notebook.remove_page(tab_page)
|
||||||
if self.parentNotebook.get_nth_page(page) == self.topWidget:
|
|
||||||
self.parentNotebook.remove_page(page)
|
def configure(self, window):
|
||||||
break
|
try:
|
||||||
|
self.combo_columns.set_active(self.config.get("columns"))
|
||||||
|
except:
|
||||||
|
self.combo_columns.set_active(15)
|
||||||
|
try:
|
||||||
|
self.combo_font_size.set_active(self.config.get("font_size"))
|
||||||
|
except:
|
||||||
|
self.combo_font_size.set_active(9)
|
||||||
|
self.dialog.set_transient_for(window)
|
||||||
|
self.dialog.show()
|
||||||
|
|
||||||
|
def handle_event(self, event):
|
||||||
|
self.tab_pieces.disconnect_handlers()
|
||||||
|
self.tab_pieces.clear_pieces_store()
|
||||||
|
self.tab_pieces.set_unique_id(event['unique_ID'])
|
||||||
|
self.tab_pieces.prepare_pieces_store()
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
update_files_removed = self.manager.update_files_removed
|
update_files_removed = self.manager.update_files_removed
|
||||||
|
@ -89,38 +133,29 @@ class TorrentPieces:
|
||||||
#if different torrent was selected or file priorities were changed.
|
#if different torrent was selected or file priorities were changed.
|
||||||
self.tab_pieces.disconnect_handlers()
|
self.tab_pieces.disconnect_handlers()
|
||||||
self.tab_pieces.clear_pieces_store()
|
self.tab_pieces.clear_pieces_store()
|
||||||
numPages = self.parentNotebook.get_n_pages()
|
|
||||||
for page in xrange(numPages):
|
|
||||||
if self.parentNotebook.get_nth_page(page) == self.topWidget:
|
|
||||||
break
|
|
||||||
switch_page = False
|
|
||||||
if self.parentNotebook.get_current_page() == page:
|
|
||||||
switch_page = True
|
|
||||||
self.parentNotebook.remove_page(page)
|
|
||||||
viewport = gtk.Viewport()
|
|
||||||
scrolledWindow = gtk.ScrolledWindow()
|
|
||||||
scrolledWindow.add(viewport)
|
|
||||||
scrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
|
||||||
label = gtk.Label(_("""
|
|
||||||
This is a temporary page used while the pieces tab gets built.
|
|
||||||
When operations are complete this will automatically become the
|
|
||||||
pieces tab.
|
|
||||||
"""))
|
|
||||||
label.set_alignment(0,0)
|
|
||||||
viewport.add(label)
|
|
||||||
self.parentNotebook.insert_page(scrolledWindow,gtk.Label(_("Pieces")),page)
|
|
||||||
scrolledWindow.show_all()
|
|
||||||
if switch_page:
|
|
||||||
self.parentNotebook.set_current_page(page)
|
|
||||||
self.tab_pieces.set_unique_id(unique_id)
|
self.tab_pieces.set_unique_id(unique_id)
|
||||||
self.topWidget = self.tab_pieces.prepare_pieces_store()
|
self.tab_pieces.prepare_pieces_store()
|
||||||
switch_page = False
|
|
||||||
if self.parentNotebook.get_current_page() == page:
|
|
||||||
switch_page = True
|
|
||||||
self.parentNotebook.remove_page(page)
|
|
||||||
self.parentNotebook = self.parent.notebook
|
|
||||||
self.parentNotebook.insert_page(self.topWidget, gtk.Label(_("Pieces")), page)
|
|
||||||
self.topWidget.show_all()
|
|
||||||
if switch_page:
|
|
||||||
self.parentNotebook.set_current_page(page)
|
|
||||||
self.tab_pieces.connect_handlers()
|
self.tab_pieces.connect_handlers()
|
||||||
|
|
||||||
|
def ok_pressed(self, src):
|
||||||
|
self.dialog.hide()
|
||||||
|
|
||||||
|
needs_store_update = False
|
||||||
|
if self.config.get("columns") !=\
|
||||||
|
self.combo_columns.get_active()\
|
||||||
|
or self.config.get("font_size") !=\
|
||||||
|
self.combo_font_size.get_active():
|
||||||
|
needs_store_update = True
|
||||||
|
|
||||||
|
self.config.set("columns",
|
||||||
|
self.combo_columns.get_active())
|
||||||
|
self.config.set("font_size",
|
||||||
|
self.combo_font_size.get_active())
|
||||||
|
self.tab_pieces.set_columns(self.combo_columns.get_active())
|
||||||
|
self.tab_pieces.set_font_size(self.combo_font_size.get_active())
|
||||||
|
if needs_store_update:
|
||||||
|
self.tab_pieces.clear_pieces_store(clear_unique_id=False)
|
||||||
|
self.tab_pieces.prepare_pieces_store()
|
||||||
|
|
||||||
|
def cancel_pressed(self, src):
|
||||||
|
self.dialog.hide()
|
||||||
|
|
|
@ -2,19 +2,22 @@ import gtk
|
||||||
import math
|
import math
|
||||||
|
|
||||||
class PiecesTabManager(object):
|
class PiecesTabManager(object):
|
||||||
def __init__(self, manager):
|
def __init__(self, manager, viewport, columns, font_size):
|
||||||
self.vbox = None
|
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
self.progress = []
|
self.viewport = viewport
|
||||||
self.tooltips = []
|
self.font_desc = None
|
||||||
self.eventboxes = []
|
self.set_font_size(font_size)
|
||||||
self.rows = 0
|
self.columns = columns
|
||||||
self.columns = 33
|
self.vbox = None
|
||||||
self.piece_width = 30
|
self.pieces = {}
|
||||||
self.piece_height = 20
|
self.labels = []
|
||||||
|
self.rows = []
|
||||||
|
self.pieces_block_info = {}
|
||||||
|
self.speed_symbols = {}
|
||||||
|
self.num_blocks = 0
|
||||||
|
self.last_num_blocks = 0
|
||||||
|
self.row = -1
|
||||||
self.unique_id = -1
|
self.unique_id = -1
|
||||||
self.peer_speed = []
|
|
||||||
self.piece_info = []
|
|
||||||
self.all_files = None
|
self.all_files = None
|
||||||
self.file_priorities = None
|
self.file_priorities = None
|
||||||
self.index = 0
|
self.index = 0
|
||||||
|
@ -29,54 +32,70 @@ class PiecesTabManager(object):
|
||||||
def set_unique_id(self, unique_id):
|
def set_unique_id(self, unique_id):
|
||||||
self.unique_id = unique_id
|
self.unique_id = unique_id
|
||||||
|
|
||||||
def clear_pieces_store(self):
|
def clear_pieces_store(self, clear_unique_id=True):
|
||||||
self.unique_id = -1
|
self.pieces = {}
|
||||||
self.rows = 0
|
self.pieces_block_info = {}
|
||||||
self.peer_speed = []
|
self.speed_symbols = {}
|
||||||
self.eventboxes = []
|
self.labels = []
|
||||||
self.progress = []
|
self.rows = []
|
||||||
self.piece_info = []
|
self.row = -1
|
||||||
self.tooltips = []
|
if clear_unique_id:
|
||||||
|
self.unique_id = -1
|
||||||
self.all_files = None
|
self.all_files = None
|
||||||
self.file_priorities = None
|
self.file_priorities = None
|
||||||
self.current_first_index = None
|
|
||||||
self.current_last_index = None
|
|
||||||
self.index = 0
|
self.index = 0
|
||||||
self.num_files = 0
|
|
||||||
self.prev_file_index = -1
|
self.prev_file_index = -1
|
||||||
self.file_index = 0
|
self.file_index = 0
|
||||||
self.next_file_index = 1
|
self.next_file_index = 1
|
||||||
|
self.num_files = 0
|
||||||
|
self.current_first_index = None
|
||||||
|
self.current_last_index = None
|
||||||
if not self.vbox is None:
|
if not self.vbox is None:
|
||||||
self.vbox.destroy()
|
self.vbox.destroy()
|
||||||
self.vbox = None
|
self.vbox = None
|
||||||
|
|
||||||
|
def set_columns(self, columns):
|
||||||
|
self.columns = columns
|
||||||
|
|
||||||
|
def set_font_size(self, font_size):
|
||||||
|
import pango
|
||||||
|
self.font_desc = pango.FontDescription('monospace %s' % font_size)
|
||||||
|
|
||||||
def prepare_pieces_store(self):
|
def prepare_pieces_store(self):
|
||||||
gtk.main_iteration_do(False)
|
gtk.main_iteration_do(False)
|
||||||
viewport = gtk.Viewport()
|
|
||||||
scrolledWindow = gtk.ScrolledWindow()
|
|
||||||
scrolledWindow.add(viewport)
|
|
||||||
scrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
|
||||||
self.vbox = gtk.VBox()
|
self.vbox = gtk.VBox()
|
||||||
viewport.add(self.vbox)
|
self.viewport.add(self.vbox)
|
||||||
|
torrent_state = self.manager.get_torrent_state(self.unique_id)
|
||||||
|
if torrent_state['is_seed']:
|
||||||
|
label = gtk.Label(_("Torrent complete"))
|
||||||
|
label.set_alignment(0,0)
|
||||||
|
self.vbox.pack_start(label, expand=False)
|
||||||
|
self.vbox.show_all()
|
||||||
|
return
|
||||||
self.all_files = self.manager.get_file_piece_range(self.unique_id)
|
self.all_files = self.manager.get_file_piece_range(self.unique_id)
|
||||||
|
self.num_blocks = self.all_files[0]['first_num_blocks']
|
||||||
|
self.last_num_blocks = self.all_files[len(self.all_files)-1]['last_num_blocks']
|
||||||
self.file_priorities = self.manager.get_priorities(self.unique_id)
|
self.file_priorities = self.manager.get_priorities(self.unique_id)
|
||||||
state = self.manager.get_torrent_state(self.unique_id)
|
state = self.manager.get_torrent_state(self.unique_id)
|
||||||
self.num_pieces = state["num_pieces"]
|
self.num_pieces = state["num_pieces"]
|
||||||
for priority in self.file_priorities:
|
for priority in self.file_priorities:
|
||||||
self.current_first_index = self.all_files[self.file_index]['first_index']
|
try:
|
||||||
self.current_last_index = self.all_files[self.file_index]['last_index']
|
self.current_first_index = self.all_files[self.file_index]['first_index']
|
||||||
if priority > 0:
|
self.current_last_index = self.all_files[self.file_index]['last_index']
|
||||||
#if file is being downloaded build the file pieces information
|
except:
|
||||||
self.build_file_pieces()
|
print "length of all_files", len(self.all_files)
|
||||||
|
print "length of file_priorities", len(self.file_priorities)
|
||||||
|
print "file index", self.file_index
|
||||||
else:
|
else:
|
||||||
#if file is not being downloaded skip the file pieces
|
if priority > 0:
|
||||||
self.skip_current_file()
|
#if file is being downloaded build the file pieces information
|
||||||
self.file_index += 1
|
self.build_file_pieces()
|
||||||
self.next_file_index += 1
|
self.file_index += 1
|
||||||
self.prev_file_index += 1
|
self.next_file_index += 1
|
||||||
|
self.prev_file_index += 1
|
||||||
self.get_current_pieces_info()
|
self.get_current_pieces_info()
|
||||||
return scrolledWindow
|
self.vbox.show_all()
|
||||||
|
return
|
||||||
|
|
||||||
def build_file_pieces(self):
|
def build_file_pieces(self):
|
||||||
gtk.main_iteration_do(False)
|
gtk.main_iteration_do(False)
|
||||||
|
@ -84,34 +103,20 @@ class PiecesTabManager(object):
|
||||||
label.set_alignment(0,0)
|
label.set_alignment(0,0)
|
||||||
label.set_text(self.all_files[self.file_index]['path'])
|
label.set_text(self.all_files[self.file_index]['path'])
|
||||||
self.vbox.pack_start(label, expand=False)
|
self.vbox.pack_start(label, expand=False)
|
||||||
table = gtk.Table()
|
|
||||||
self.rows = int(math.ceil((self.current_last_index-self.current_first_index)/self.columns)+1)
|
|
||||||
self.vbox.pack_start(table, expand=False)
|
|
||||||
table.resize(self.rows, self.columns)
|
|
||||||
table.set_size_request((self.columns+1)*self.piece_width, (self.rows+1)*self.piece_height)
|
|
||||||
if self.current_last_index != self.current_first_index:
|
if self.current_last_index != self.current_first_index:
|
||||||
#if there is more than one piece
|
#if there is more than one piece
|
||||||
self.build_pieces_table(table)
|
self.build_pieces_table()
|
||||||
only_one_piece = False
|
self.vbox.pack_start(gtk.Label(), expand=False)
|
||||||
else:
|
else:
|
||||||
#if file only has one piece
|
#if file only has one piece
|
||||||
self.index = 0
|
self.index = 0
|
||||||
only_one_piece = True
|
|
||||||
self.piece_info.append({'blocks_total':0, 'blocks_finished':0, 'blocks_requested':0})
|
|
||||||
self.progress.append(gtk.ProgressBar())
|
|
||||||
self.tooltips.append(gtk.Tooltips())
|
|
||||||
self.eventboxes.append(gtk.EventBox())
|
|
||||||
self.peer_speed.append("unknown")
|
|
||||||
main_index = self.current_last_index
|
main_index = self.current_last_index
|
||||||
if self.file_index > 0 and not self.piece_info[main_index] is None and only_one_piece:
|
if self.file_index == 0 or not main_index in self.pieces:
|
||||||
#if file has only one piece and it is shared destroy the table
|
|
||||||
table.destroy()
|
|
||||||
if self.file_index == 0 or self.piece_info[main_index] is None or not only_one_piece:
|
|
||||||
# piece could be shared if file has only one piece and it's not the first file
|
# piece could be shared if file has only one piece and it's not the first file
|
||||||
# only create it if it does not exist
|
# only create it if it does not exist
|
||||||
self.build_last_file_piece(table, main_index, only_one_piece)
|
self.build_last_file_piece(main_index)
|
||||||
|
|
||||||
def build_pieces_table(self, table):
|
def build_pieces_table(self):
|
||||||
temp_prev_priority = 1
|
temp_prev_priority = 1
|
||||||
if self.file_index == 0\
|
if self.file_index == 0\
|
||||||
or self.current_first_index !=\
|
or self.current_first_index !=\
|
||||||
|
@ -131,175 +136,181 @@ class PiecesTabManager(object):
|
||||||
diff = 0
|
diff = 0
|
||||||
temp_range = self.current_last_index-self.current_first_index
|
temp_range = self.current_last_index-self.current_first_index
|
||||||
#last piece handled outside of loop, skip it from range
|
#last piece handled outside of loop, skip it from range
|
||||||
|
row_prev = 0
|
||||||
for index in xrange(temp_range):
|
for index in xrange(temp_range):
|
||||||
gtk.main_iteration_do(False)
|
gtk.main_iteration_do(False)
|
||||||
main_index = diff+self.current_first_index+index
|
main_index = diff+self.current_first_index+index
|
||||||
if temp_prev_priority > 0:
|
|
||||||
#normal behavior
|
|
||||||
self.piece_info.append({'blocks_total':0, 'blocks_finished':0, 'blocks_requested':0})
|
|
||||||
self.progress.append(gtk.ProgressBar())
|
|
||||||
self.tooltips.append(gtk.Tooltips())
|
|
||||||
self.eventboxes.append(gtk.EventBox())
|
|
||||||
self.peer_speed.append("unknown")
|
|
||||||
else:
|
|
||||||
#if first piece is shared with a skipped file
|
|
||||||
self.share_skipped_piece(main_index)
|
|
||||||
temp_prev_priority = 1
|
|
||||||
self.progress[main_index].set_size_request(self.piece_width, self.piece_height)
|
|
||||||
row = index/self.columns
|
row = index/self.columns
|
||||||
column = index%self.columns
|
column = index%self.columns
|
||||||
table.attach(self.eventboxes[main_index], column, column+1, row, row+1,
|
if row == 0 and column == 0:
|
||||||
xoptions=0, yoptions=0, xpadding=0, ypadding=0)
|
self.row += 1
|
||||||
self.eventboxes[main_index].add(self.progress[main_index])
|
self.rows.append([])
|
||||||
|
self.labels.append(gtk.Label())
|
||||||
|
self.labels[row].set_alignment(0,0)
|
||||||
|
self.vbox.pack_start(self.labels[self.row], expand=False)
|
||||||
|
if row > row_prev:
|
||||||
|
self.row += 1
|
||||||
|
row_list = {}
|
||||||
|
self.rows.append([])
|
||||||
|
self.labels.append(gtk.Label())
|
||||||
|
self.labels[row].set_alignment(0,0)
|
||||||
|
self.vbox.pack_start(self.labels[self.row], expand=False)
|
||||||
|
percentage = " 0% "
|
||||||
|
self.pieces[main_index] = {'row':self.row, 'column':column}
|
||||||
|
self.pieces_block_info[main_index] = 0
|
||||||
|
self.speed_symbols[main_index] = " "
|
||||||
|
row_prev = row
|
||||||
if self.manager.has_piece(self.unique_id, main_index):
|
if self.manager.has_piece(self.unique_id, main_index):
|
||||||
#if piece is already finished
|
#if piece is already finished
|
||||||
self.progress[main_index].set_fraction(1)
|
percentage = " 100% "
|
||||||
self.tooltips[main_index].set_tip(self.eventboxes[main_index], _("Piece finished"))
|
self.pieces_block_info[main_index] = self.num_blocks
|
||||||
else:
|
self.rows[self.row].append(percentage)
|
||||||
#if piece is not already finished
|
self.labels[self.row].modify_font(self.font_desc)
|
||||||
self.tooltips[main_index].set_tip(self.eventboxes[main_index], _("Piece not started"))
|
self.labels[self.row].set_text(str(self.rows[self.row]))
|
||||||
|
self.labels[self.row].set_alignment(0,0)
|
||||||
self.index = temp_range
|
self.index = temp_range
|
||||||
|
|
||||||
def build_last_file_piece(self, table, main_index, only_one_piece):
|
def build_last_file_piece(self, main_index):
|
||||||
gtk.main_iteration_do(False)
|
gtk.main_iteration_do(False)
|
||||||
if only_one_piece and self.file_index > 0:
|
|
||||||
#if piece is shared with a skipped file
|
|
||||||
self.share_skipped_piece(main_index)
|
|
||||||
self.progress[main_index].set_size_request(self.piece_width, self.piece_height)
|
|
||||||
if self.next_file_index < len(self.all_files):
|
if self.next_file_index < len(self.all_files):
|
||||||
# if there is another file
|
# if there is another file
|
||||||
if self.file_priorities[self.next_file_index]==0\
|
if self.file_priorities[self.next_file_index]==0\
|
||||||
or self.current_last_index != self.all_files[self.next_file_index]['first_index']:
|
or self.current_last_index != self.all_files[self.next_file_index]['first_index']:
|
||||||
#if next file is skipped or there is no shared piece, keep last piece
|
#if next file is skipped or there is no shared piece, keep last piece
|
||||||
row=self.index/self.columns
|
row = self.index/self.columns
|
||||||
column=self.index%self.columns
|
column = self.index%self.columns
|
||||||
table.attach(self.eventboxes[main_index], column, column+1, row, row+1,
|
if column == 0:
|
||||||
xoptions=0, yoptions=0, xpadding=0, ypadding=0)
|
self.row += 1
|
||||||
self.eventboxes[main_index].add(self.progress[main_index])
|
self.labels.append(gtk.Label())
|
||||||
|
self.vbox.pack_start(self.labels[self.row], expand=False)
|
||||||
|
self.rows.append([])
|
||||||
|
self.pieces[main_index] = {'row':self.row, 'column':column}
|
||||||
if self.file_priorities[self.next_file_index]>0\
|
if self.file_priorities[self.next_file_index]>0\
|
||||||
and self.current_last_index == self.all_files[self.next_file_index]['first_index']:
|
and self.current_last_index == self.all_files[self.next_file_index]['first_index']:
|
||||||
#if next file is not skipped and there is a shared piece, do not keep last piece
|
#if next file is not skipped and there is a shared piece, do not keep last piece
|
||||||
if only_one_piece:
|
self.row += 1
|
||||||
#only piece in file is shared, destroy table for file
|
|
||||||
table.destroy()
|
|
||||||
label = gtk.Label()
|
label = gtk.Label()
|
||||||
label.set_alignment(0,0)
|
label.set_alignment(0,0)
|
||||||
label.set_text(_("Piece shared with next file(s)"))
|
label.set_text(_("Piece shared with next file(s)"))
|
||||||
self.vbox.pack_start(label, expand=False)
|
self.vbox.pack_start(label, expand=False)
|
||||||
temp_table = gtk.Table()
|
self.labels.append(gtk.Label())
|
||||||
temp_table.resize(1,2)
|
self.vbox.pack_start(self.labels[self.row], expand=False)
|
||||||
temp_table.set_size_request(self.piece_width, 2*self.piece_height)
|
self.vbox.pack_start(gtk.Label(), expand=False)
|
||||||
temp_table.attach(self.eventboxes[main_index], 0, 1, 0, 1,
|
self.rows.append([])
|
||||||
xoptions=0, yoptions=0, xpadding=0, ypadding=0)
|
self.pieces[main_index] = {'row':self.row, 'column':0}
|
||||||
self.eventboxes[main_index].add(self.progress[main_index])
|
|
||||||
self.vbox.pack_start(temp_table, expand=False)
|
|
||||||
else:
|
else:
|
||||||
#if there is no other file
|
#if there is no other file
|
||||||
row=self.index/self.columns
|
row = self.index/self.columns
|
||||||
column=self.index%self.columns
|
column = self.index%self.columns
|
||||||
table.attach(self.eventboxes[main_index], column, column+1, row, row+1,
|
if column == 0:
|
||||||
xoptions=0, yoptions=0, xpadding=0, ypadding=0)
|
self.row += 1
|
||||||
self.eventboxes[main_index].add(self.progress[main_index])
|
self.labels.append(gtk.Label())
|
||||||
|
self.rows.append([])
|
||||||
|
self.pieces[main_index] = {'row':self.row, 'column':column}
|
||||||
|
percentage = " 0% "
|
||||||
|
self.pieces_block_info[main_index] = 0
|
||||||
|
self.speed_symbols[main_index] = " "
|
||||||
if self.manager.has_piece(self.unique_id, main_index):
|
if self.manager.has_piece(self.unique_id, main_index):
|
||||||
#if the last piece is already finished
|
#if piece is already finished
|
||||||
self.progress[main_index].set_fraction(1)
|
percentage = " 100% "
|
||||||
self.tooltips[main_index].set_tip(self.eventboxes[main_index], _("Piece finished"))
|
self.pieces_block_info[main_index] = self.num_blocks
|
||||||
else:
|
self.rows[self.row].append(percentage)
|
||||||
#if the last piece is not already finished
|
self.labels[self.row].modify_font(self.font_desc)
|
||||||
self.tooltips[main_index].set_tip(self.eventboxes[main_index], _("Piece not started"))
|
self.labels[self.row].set_text(str(self.rows[self.row]))
|
||||||
|
self.labels[self.row].set_alignment(0,0)
|
||||||
def share_skipped_piece(self, main_index):
|
|
||||||
self.piece_info[main_index] = {'blocks_total':0, 'blocks_finished':0, 'blocks_requested':0}
|
|
||||||
self.progress[main_index] = gtk.ProgressBar()
|
|
||||||
self.tooltips[main_index] = gtk.Tooltips()
|
|
||||||
self.eventboxes[main_index] = gtk.EventBox()
|
|
||||||
self.peer_speed[main_index] = "unknown"
|
|
||||||
|
|
||||||
def skip_current_file(self):
|
|
||||||
if self.file_index == 0\
|
|
||||||
or self.current_first_index !=\
|
|
||||||
self.all_files[self.prev_file_index]['last_index']:
|
|
||||||
#if first piece is not shared
|
|
||||||
temp_range = 1+self.current_last_index-self.current_first_index
|
|
||||||
else:
|
|
||||||
#if first piece is shared
|
|
||||||
temp_range = self.current_last_index-self.current_first_index
|
|
||||||
for index in xrange(temp_range):
|
|
||||||
self.piece_info.append(None)
|
|
||||||
self.progress.append(None)
|
|
||||||
self.eventboxes.append(None)
|
|
||||||
self.tooltips.append(None)
|
|
||||||
self.peer_speed.append(None)
|
|
||||||
|
|
||||||
def connect_handlers(self):
|
def connect_handlers(self):
|
||||||
self.handlers_connected = True
|
self.handlers_connected = True
|
||||||
self.manager.connect_event(self.manager.constants['EVENT_PIECE_FINISHED'], self.handle_event)
|
self.manager.connect_event(self.manager.constants['EVENT_PIECE_FINISHED'], self.handle_event)
|
||||||
self.manager.connect_event(self.manager.constants['EVENT_BLOCK_FINISHED'], self.handle_event)
|
self.manager.connect_event(self.manager.constants['EVENT_BLOCK_FINISHED'], self.handle_event)
|
||||||
self.manager.connect_event(self.manager.constants['EVENT_BLOCK_DOWNLOADING'], self.handle_event)
|
self.manager.connect_event(self.manager.constants['EVENT_BLOCK_DOWNLOADING'], self.handle_event)
|
||||||
|
self.manager.connect_event(self.manager.constants['EVENT_HASH_FAILED_ERROR'], self.handle_event)
|
||||||
|
|
||||||
def disconnect_handlers(self):
|
def disconnect_handlers(self):
|
||||||
if self.handlers_connected:
|
if self.handlers_connected:
|
||||||
self.manager.disconnect_event(self.manager.constants['EVENT_PIECE_FINISHED'], self.handle_event)
|
self.manager.disconnect_event(self.manager.constants['EVENT_PIECE_FINISHED'], self.handle_event)
|
||||||
self.manager.disconnect_event(self.manager.constants['EVENT_BLOCK_FINISHED'], self.handle_event)
|
self.manager.disconnect_event(self.manager.constants['EVENT_BLOCK_FINISHED'], self.handle_event)
|
||||||
self.manager.disconnect_event(self.manager.constants['EVENT_BLOCK_DOWNLOADING'], self.handle_event)
|
self.manager.disconnect_event(self.manager.constants['EVENT_BLOCK_DOWNLOADING'], self.handle_event)
|
||||||
|
self.manager.disconnect_event(self.manager.constants['EVENT_HASH_FAILED_ERROR'], self.handle_event)
|
||||||
self.handlers_connected = False
|
self.handlers_connected = False
|
||||||
|
|
||||||
def handle_event(self, event):
|
def handle_event(self, event):
|
||||||
#protect against pieces trying to display after file priority changed
|
#protect against pieces trying to display after file priority changed
|
||||||
#or different torrent selected
|
#or different torrent selected
|
||||||
if event['unique_ID'] == self.unique_id\
|
if event['unique_ID'] == self.unique_id\
|
||||||
and not self.piece_info[event['piece_index']] is None:
|
and event['piece_index'] in self.pieces:
|
||||||
|
index = event['piece_index']
|
||||||
|
row = self.pieces[index]['row']
|
||||||
|
column = self.pieces[index]['column']
|
||||||
if event['event_type'] is self.manager.constants['EVENT_PIECE_FINISHED']:
|
if event['event_type'] is self.manager.constants['EVENT_PIECE_FINISHED']:
|
||||||
self.update_pieces_store(event['piece_index'], piece_finished=True)
|
self.rows[row][column] = " 100% "
|
||||||
|
if index == self.all_files[len(self.all_files)-1]['last_index']:
|
||||||
|
self.pieces_block_info[index] = self.last_num_blocks
|
||||||
|
else:
|
||||||
|
self.pieces_block_info[index] = self.num_blocks
|
||||||
|
self.labels[row].set_text(str(self.rows[row]))
|
||||||
|
elif event['event_type'] is self.manager.constants['EVENT_HASH_FAILED_ERROR']:
|
||||||
|
self.rows[row][column] = " 0% "
|
||||||
|
self.pieces_block_info[index] = 0
|
||||||
elif event['event_type'] is self.manager.constants['EVENT_BLOCK_DOWNLOADING']:
|
elif event['event_type'] is self.manager.constants['EVENT_BLOCK_DOWNLOADING']:
|
||||||
index = event['piece_index']
|
if index == self.all_files[len(self.all_files)-1]['last_index']:
|
||||||
if self.piece_info[index]['blocks_total'] == 0:
|
percentage = (100*self.pieces_block_info[index])/self.last_num_blocks
|
||||||
self.piece_info[index] = self.manager.get_piece_info(self.unique_id, index)
|
|
||||||
temp_peer_speed = event['peer_speed']
|
|
||||||
if temp_peer_speed == "fast":
|
|
||||||
peer_speed_msg = _("fast")
|
|
||||||
elif temp_peer_speed == "slow":
|
|
||||||
peer_speed_msg = _("slow")
|
|
||||||
elif temp_peer_speed == "medium":
|
|
||||||
peer_speed_msg = _("medium")
|
|
||||||
else:
|
else:
|
||||||
peer_speed_msg = _("unknown")
|
percentage = (100*self.pieces_block_info[index])/self.num_blocks
|
||||||
self.peer_speed[index] = peer_speed_msg
|
# Pad accordingly
|
||||||
self.update_pieces_store(index)
|
symbol = " "
|
||||||
else:
|
if event['peer_speed'] == "fast":
|
||||||
index = event['piece_index']
|
symbol = "+"
|
||||||
if self.piece_info[index]['blocks_total'] == 0:
|
elif event['peer_speed'] == "medium":
|
||||||
self.piece_info[index] = self.manager.get_piece_info(self.unique_id, index)
|
symbol = "="
|
||||||
|
elif event['peer_speed'] == "slow":
|
||||||
|
symbol = "-"
|
||||||
|
percentage_label = " "
|
||||||
|
if percentage < 99:
|
||||||
|
if percentage <= 9:
|
||||||
|
percentage_label = " "
|
||||||
|
else:
|
||||||
|
percentage_label = " "
|
||||||
|
self.speed_symbols[index] = symbol
|
||||||
|
percentage_label = symbol + percentage_label + str(percentage) + "% "
|
||||||
|
self.rows[row][column] = percentage_label
|
||||||
|
self.labels[row].set_text(str(self.rows[row]))
|
||||||
|
else: # block finished
|
||||||
|
self.pieces_block_info[index] += 1
|
||||||
|
if index == self.all_files[len(self.all_files)-1]['last_index']:
|
||||||
|
percentage = (100*self.pieces_block_info[index])/self.last_num_blocks
|
||||||
else:
|
else:
|
||||||
self.piece_info[index]['blocks_finished'] += 1
|
percentage = (100*self.pieces_block_info[index])/self.num_blocks
|
||||||
self.update_pieces_store(event['piece_index'])
|
# Pad accordingly
|
||||||
|
percentage_label = " "
|
||||||
|
if percentage < 99:
|
||||||
|
if percentage <= 9:
|
||||||
|
percentage_label = " "
|
||||||
|
else:
|
||||||
|
percentage_label = " "
|
||||||
|
percentage_label = self.speed_symbols[index] + percentage_label + str(percentage) + "% "
|
||||||
|
self.rows[row][column] = percentage_label
|
||||||
|
self.labels[row].set_text(str(self.rows[row]))
|
||||||
|
|
||||||
def get_current_pieces_info(self):
|
def get_current_pieces_info(self):
|
||||||
all_piece_info = self.manager.get_all_piece_info(self.unique_id)
|
all_piece_info = self.manager.get_all_piece_info(self.unique_id)
|
||||||
for piece_index in all_piece_info:
|
for info_index in xrange(len(all_piece_info)):
|
||||||
index = piece_index['piece_index']
|
index = all_piece_info[info_index]['piece_index']
|
||||||
if not self.piece_info[index] is None:
|
if index in self.pieces:
|
||||||
temp_piece_info = {'blocks_total':piece_index['blocks_total'], \
|
row = self.pieces[index]['row']
|
||||||
'blocks_finished':piece_index['blocks_finished']}
|
column = self.pieces[index]['column']
|
||||||
self.piece_info[index] = temp_piece_info
|
if index == self.all_files[len(self.all_files)-1]['last_index']:
|
||||||
blocks_total = str(temp_piece_info['blocks_total'])
|
percentage = (100*self.pieces_block_info[index])/self.last_num_blocks
|
||||||
info_string = str(temp_piece_info['blocks_finished']) + "/" + blocks_total + " " + _("blocks finished") + "\n" \
|
else:
|
||||||
+ _("peer speed: unknown")
|
percentage = (100*self.pieces_block_info[index])/self.num_blocks
|
||||||
if self.progress[index].get_fraction() == 0:
|
# Pad accordingly
|
||||||
self.progress[index].set_fraction(0.5)
|
label = " "
|
||||||
self.tooltips[index].set_tip(self.eventboxes[index], info_string)
|
if percentage < 99:
|
||||||
|
if percentage <= 9:
|
||||||
|
label = " "
|
||||||
|
else:
|
||||||
|
label = " "
|
||||||
|
label = label + str(percentage) + "% "
|
||||||
|
self.rows[row][column] = label
|
||||||
|
self.labels[row].set_text(str(self.rows[row]))
|
||||||
|
|
||||||
def update_pieces_store(self, index, piece_finished=False):
|
|
||||||
if piece_finished:
|
|
||||||
self.progress[index].set_fraction(1)
|
|
||||||
self.tooltips[index].set_tip(self.eventboxes[index], _("Piece finished"))
|
|
||||||
else:
|
|
||||||
temp_fraction = self.progress[index].get_fraction()
|
|
||||||
if temp_fraction == 0:
|
|
||||||
self.progress[index].set_fraction(0.5)
|
|
||||||
if temp_fraction != 1:
|
|
||||||
temp_piece_info = self.piece_info[index]
|
|
||||||
blocks_total = str(temp_piece_info['blocks_total'])
|
|
||||||
info_string = str(temp_piece_info['blocks_finished']) + "/" + blocks_total + " " + _("blocks finished") + "\n" \
|
|
||||||
+ _("peer speed: ") + self.peer_speed[index]
|
|
||||||
self.tooltips[index].set_tip(self.eventboxes[index], info_string)
|
|
||||||
|
|
|
@ -1292,6 +1292,7 @@ static PyObject *torrent_get_file_piece_range(PyObject *self, PyObject *args)
|
||||||
|
|
||||||
torrent_info const &info = M_torrents->at(index).handle.get_torrent_info();
|
torrent_info const &info = M_torrents->at(index).handle.get_torrent_info();
|
||||||
int file_index = 0;
|
int file_index = 0;
|
||||||
|
size_type first_num_blocks, last_num_blocks;
|
||||||
PyObject *file_info;
|
PyObject *file_info;
|
||||||
|
|
||||||
for(torrent_info::file_iterator i = info.begin_files(); i != info.end_files(); ++i)
|
for(torrent_info::file_iterator i = info.begin_files(); i != info.end_files(); ++i)
|
||||||
|
@ -1299,10 +1300,14 @@ static PyObject *torrent_get_file_piece_range(PyObject *self, PyObject *args)
|
||||||
file_entry const &currFile = (*i);
|
file_entry const &currFile = (*i);
|
||||||
peer_request first_index = info.map_file(file_index, 0, 1);
|
peer_request first_index = info.map_file(file_index, 0, 1);
|
||||||
peer_request last_index = info.map_file(file_index, currFile.size-1, 1);
|
peer_request last_index = info.map_file(file_index, currFile.size-1, 1);
|
||||||
|
first_num_blocks = info.piece_length()/(16 * 1024);
|
||||||
|
last_num_blocks = ceil((double)(info.piece_size(last_index.piece))/(16 * 1024));
|
||||||
file_info = Py_BuildValue(
|
file_info = Py_BuildValue(
|
||||||
"{s:i,s:i,s:s}",
|
"{s:i,s:i,s:i,s:i,s:s}",
|
||||||
"first_index", first_index.piece,
|
"first_index", first_index.piece,
|
||||||
"last_index", last_index.piece,
|
"last_index", last_index.piece,
|
||||||
|
"first_num_blocks", (int)first_num_blocks,
|
||||||
|
"last_num_blocks", (int)last_num_blocks,
|
||||||
"path", currFile.path.string().c_str()
|
"path", currFile.path.string().c_str()
|
||||||
);
|
);
|
||||||
file_index++;
|
file_index++;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue