📄 btdownloadgui.py
字号:
self.treeview.set_headers_visible(False) self.treeview.columns_autosize() self.sw.show_all() self.treeview.realize() for column in cs: column.set_fixed_width(column.get_width()) column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) self.treeview.set_headers_visible(True) self.store.clear() self.treeview.get_selection().set_mode(gtk.SELECTION_NONE) width = self.treeview.size_request()[0] self.win.set_default_size(width+SCROLLBAR_WIDTH, 300) self.win.show_all() self.prev = [] def update(self, peers, bad_peers): fields = [] def p_bool(value): return value and '*' or '' for peer in peers: field = [] field.append(peer['ip']) client, version = ClientIdentifier.identify_client(peer['id']) field.append(client + ' ' + version) if advanced_ui: field.append(quote(peer['id'])) field.append(peer['initiation'] == 'R' and 'remote' or 'local') dl = peer['download'] ul = peer['upload'] for l in (dl, ul): rate = l[1] if rate > 100: field.append(int(round(rate/(2**10)))) else: field.append(0) if advanced_ui: field.append(p_bool(l[2])) field.append(p_bool(l[3])) if len(l) > 4: field.append(p_bool(l[4])) else: field.append(p_bool(peer['is_optimistic_unchoke'])) field.append('%.2f'%round(dl[0] / 2**20, 2)) field.append('%.2f'%round(ul[0] / 2**20, 2)) field.append('%.1f'%round(int(peer['completed']*1000)/10, 1)) field.append(int(peer['speed']//(2**10))) fields.append(field) for (ip, (is_banned, stats)) in bad_peers.iteritems(): field = [] field.append(ip) client, version = ClientIdentifier.identify_client(stats.peerid) field.append(client + ' ' + version) if advanced_ui: field.append(quote(stats.peerid)) field.append('bad peer') # the sortable peer list won't take strings in these fields field.append(0) if advanced_ui: field.extend([0] * 7) # upRate, * fields else: field.extend([0] * 1) # upRate field.append("%d ok" % stats.numgood) field.append("%d bad" % len(stats.bad)) if is_banned: # completion field.append('banned') else: field.append('ok') field.append(0) # peer dl rate fields.append(field) if self.store.get_sort_column_id() < 0: # ListStore is unsorted, it might be faster to set only modified fields it = self.store.get_iter_first() for old, new in itertools.izip(self.prev, fields): if old != new: for i, value in enumerate(new): if value != old[i]: self.store.set_value(it, i, value) it = self.store.iter_next(it) for i in range(len(fields), len(self.prev)): self.store.remove(it) for i in range(len(self.prev), len(fields)): self.store.append(fields[i]) self.prev = fields else: # ListStore is sorted, no reason not to to reset all fields self.store.clear() for field in fields: self.store.append(field) def close(self): self.win.destroy()class TorrentInfoWindow(object): def __init__(self, torrent_box, closefunc): self.win = Window() self.torrent_box = torrent_box name = self.torrent_box.metainfo.name self.win.set_title('Info for "%s"'%name) self.win.set_size_request(-1,-1) self.win.set_border_width(SPACING) self.win.set_resizable(False) self.win.connect('destroy', closefunc) self.vbox = gtk.VBox(spacing=SPACING) self.table = gtk.Table(rows=4, columns=3, homogeneous=False) self.table.set_row_spacings(SPACING) self.table.set_col_spacings(SPACING) y = 0 def add_item(key, val, y): self.table.attach(ralign(gtk.Label(key)), 0, 1, y, y+1) v = gtk.Label(val) v.set_selectable(True) self.table.attach(lalign(v), 1, 2, y, y+1) add_item('Torrent name:', name, y) y+=1 add_item('Announce url:', self.torrent_box.metainfo.announce, y) y+=1 size = Size(self.torrent_box.metainfo.total_bytes) num_files = ', in one file' if self.torrent_box.is_batch: num_files = ', in %d files' % len(self.torrent_box.metainfo.sizes) add_item('Total size:', str(size)+num_files, y) y+=1 if advanced_ui: pl = self.torrent_box.metainfo.piece_length count, lastlen = divmod(size, pl) sizedetail = '%d x %d + %d = %d' % (count, pl, lastlen, int(size)) add_item('Pieces:', sizedetail, y) y+=1 add_item('Info hash:', self.torrent_box.infohash.encode('hex'), y) y+=1 path = self.torrent_box.dlpath filename = '' if not self.torrent_box.is_batch: path,filename = os.path.split(self.torrent_box.dlpath) if path[-1] != os.sep: path += os.sep add_item('Save in:', path, y) y+=1 if not self.torrent_box.is_batch: add_item('File name:', filename, y) y+=1 self.vbox.pack_start(self.table) self.vbox.pack_start(gtk.HSeparator(), expand=False, fill=False) self.hbox = gtk.HBox(spacing=SPACING) lbbox = gtk.HButtonBox() rbbox = gtk.HButtonBox() lbbox.set_spacing(SPACING) if OpenPath.can_open_files: opendirbutton = IconButton("Open directory", stock=gtk.STOCK_OPEN) opendirbutton.connect('clicked', self.torrent_box.open_dir) lbbox.pack_start(opendirbutton, expand=False, fill=False) opendirbutton.set_sensitive(self.torrent_box.can_open_dir()) filelistbutton = IconButton("Show file list", stock='gtk-index') if self.torrent_box.is_batch: filelistbutton.connect('clicked', self.torrent_box.open_filelist) else: filelistbutton.set_sensitive(False) lbbox.pack_start(filelistbutton, expand=False, fill=False) closebutton = gtk.Button(stock='gtk-close') closebutton.connect('clicked', lambda w: self.close()) rbbox.pack_end(closebutton, expand=False, fill=False) self.hbox.pack_start(lbbox, expand=False, fill=False) self.hbox.pack_end( rbbox, expand=False, fill=False) self.vbox.pack_end(self.hbox, expand=False, fill=False) self.win.add(self.vbox) self.win.show_all() def close(self): self.win.destroy()class TorrentBox(gtk.EventBox): def __init__(self, infohash, metainfo, dlpath, completion, main): gtk.EventBox.__init__(self) self.infohash = infohash self.metainfo = metainfo self.dlpath = dlpath self.completion = completion self.main = main self.uptotal = self.main.torrents[self.infohash].uptotal self.downtotal = self.main.torrents[self.infohash].downtotal if self.downtotal > 0: self.up_down_ratio = self.uptotal / self.downtotal else: self.up_down_ratio = None self.infowindow = None self.filelistwindow = None self.is_batch = metainfo.is_batch self.menu = None self.menu_handler = None self.vbox = gtk.VBox(homogeneous=False, spacing=SPACING) self.label = gtk.Label() self.set_name() self.vbox.pack_start(lalign(self.label), expand=False, fill=False) self.hbox = gtk.HBox(homogeneous=False, spacing=SPACING) self.icon = gtk.Image() self.icon.set_size_request(-1, 29) self.iconbox = gtk.VBox() self.iconevbox = gtk.EventBox() self.iconevbox.add(self.icon) self.iconbox.pack_start(self.iconevbox, expand=False, fill=False) self.hbox.pack_start(self.iconbox, expand=False, fill=False) self.vbox.pack_start(self.hbox) self.infobox = gtk.VBox(homogeneous=False) self.progressbarbox = gtk.HBox(homogeneous=False, spacing=SPACING) self.progressbar = gtk.ProgressBar() if is_frozen_exe: # Hack around broken GTK-Wimp theme: # make progress bar text always black # see task #694 style = self.progressbar.get_style().copy() black = style.black self.progressbar.modify_fg(gtk.STATE_PRELIGHT, black) if self.completion is not None: self.progressbar.set_fraction(self.completion) if self.completion >= 1: done_label = self.make_done_label() self.progressbar.set_text(done_label) else: self.progressbar.set_text('%.1f%%'%(self.completion*100)) else: self.progressbar.set_text('?') self.progressbarbox.pack_start(self.progressbar, expand=True, fill=True) self.buttonevbox = gtk.EventBox() self.buttonbox = gtk.HBox(homogeneous=True, spacing=SPACING) self.infobutton = gtk.Button() self.infoimage = gtk.Image() self.infoimage.set_from_stock('bt-info', gtk.ICON_SIZE_BUTTON) self.infobutton.add(self.infoimage) self.infobutton.connect('clicked', self.open_info) self.main.tooltips.set_tip(self.infobutton, 'Torrent info') self.buttonbox.pack_start(self.infobutton, expand=True) self.cancelbutton = gtk.Button() self.cancelimage = gtk.Image() if self.completion is not None and self.completion >= 1: self.cancelimage.set_from_stock('bt-remove', gtk.ICON_SIZE_BUTTON) self.main.tooltips.set_tip(self.cancelbutton, 'Remove torrent') else: self.cancelimage.set_from_stock(gtk.STOCK_CANCEL, gtk.ICON_SIZE_BUTTON) self.main.tooltips.set_tip(self.cancelbutton, 'Abort torrent') self.cancelbutton.add(self.cancelimage) self.cancelbutton.connect('clicked', self.confirm_remove) self.buttonbox.pack_start(self.cancelbutton, expand=True, fill=False) self.buttonevbox.add(self.buttonbox) vbuttonbox = gtk.VBox(homogeneous=False) vbuttonbox.pack_start(self.buttonevbox, expand=False, fill=False) self.hbox.pack_end(vbuttonbox, expand=False, fill=False) self.infobox.pack_start(self.progressbarbox, expand=False, fill=False) self.hbox.pack_start(self.infobox, expand=True, fill=True) self.add( self.vbox ) self.drag_source_set(gtk.gdk.BUTTON1_MASK, [BT_TARGET], gtk.gdk.ACTION_MOVE) self.connect('drag_data_get', self.drag_data_get) self.connect('drag_begin' , self.drag_begin ) self.connect('drag_end' , self.drag_end ) self.cursor_handler_id = self.connect('enter_notify_event', self.change_cursors) def change_cursors(self, *args): # BUG: this is in a handler that is disconnected because the # window attributes are None until after show_all() is called self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2)) self.buttonevbox.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)) self.disconnect(self.cursor_handler_id) def drag_data_get(self, widget, context, selection, targetType, eventTime): selection.set(selection.target, 8, self.infohash) def drag_begin(self, *args): pass def drag_end(self, *args): self.main.drag_end() def make_done_label(self, statistics=None): s = '' if statistics and statistics['timeEst'] is not None: s = ', will seed for %s' % Duration(statistics['timeEst']) elif statistics: s = ', will seed indefinitely.' if self.up_down_ratio is not None: done_label = 'Done, share ratio: %d%%' % \ (self.up_down_ratio*100) + s elif statistics is not None:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -