📄 downloadmanager.py
字号:
self.gauges = [] self.gauge_types = {0 : NullGauge , 1 : SimpleDownloadGauge , 2 : ModerateDownloadGauge, 3 : FancyDownloadGauge } pbstyle = wx.the_app.config['progressbar_style'] self.change_gauge_type(pbstyle) self.Bind(wx.EVT_PAINT, self._gauge_paint) # these are a little aggressive, but GTK for example does not send paint # events during/after column resize. self.Bind(wx.EVT_LIST_COL_DRAGGING, self._gauge_paint) self.Bind(wx.EVT_LIST_COL_END_DRAG, self._gauge_paint) self.Bind(wx.EVT_SCROLL, self._gauge_paint) self.image_list_offset = self.il.GetImageCount() for name in image_names: name = ("torrentstate", name) self.add_image(wx.the_app.theme_library.get(name)) unknown = ('torrentstate', 'unknown') self.add_image(wx.the_app.theme_library.get(unknown)) self.set_default_widths() self.SetColumnWidth(self.columns['progress'].GetColumn(), 200) def SortItems(self, sorter=None): for g in self.gauges: g.invalidate() HashableListView.SortItems(self, sorter) def DeleteRow(self, itemData): HashableListView.DeleteRow(self, itemData) self._gauge_paint() def change_gauge_type(self, type_id): t = self.gauge_types[type_id] self._change_gauge_type(t) def _change_gauge_type(self, gauge_type): for g in self.gauges: g.Hide() g.Destroy() self.gauges = [] self._gauge_type = gauge_type if gauge_type == NullGauge: self.columns['progress'].renderer = lambda v: '%.1f%%'%v else: # don't draw a number under the bar when progress bars are on. self.columns['progress'].renderer = lambda v: '' self.rerender_col('progress') self._gauge_paint(resize=True) def _gauge_paint(self, event=None, resize=False): if not self.columns['progress'].enabled: if event: event.Skip() return if event: resize = True t = self.GetTopItem() b = self.GetBottomItem() while len(self.gauges) > self.GetItemCount(): gauge = self.gauges.pop() gauge.Hide() gauge.Destroy() count = self.GetItemCount() for i in xrange(count): # it might not exist yet if i >= len(self.gauges): # so make it gauge = self._gauge_type(self) self.gauges.append(gauge) resize = True if i < t or i > b: self.gauges[i].Hide() else: self.update_gauge(i, self.columns['progress'].GetColumn(), resize=resize) if event: event.Skip() def update_gauge(self, row, col, resize=False): gauge = self.gauges[row] infohash = self.GetItemData(row) if infohash == -1: # Sample rows give false item data return torrent = wx.the_app.torrents[infohash] value = torrent.completion try: value = float(value) except: value = 0.0 if resize: r = self.GetCellRect(row, col) gauge.SetDimensions(r.x + 1, r.y + 1, r.width - 2, r.height - 2) gauge.Show() else: gauge.SetValue(torrent.completion, torrent.state, torrent.piece_states) def toggle_column(self, tcolumn, id, event): HashableListView.toggle_column(self, tcolumn, id, event) if tcolumn == self.columns['progress']: if tcolumn.enabled: self._gauge_paint() else: gauges = list(self.gauges) del self.gauges[:] for gauge in gauges: gauge.Hide() gauge.Destroy() def get_selected_infohashes(self): return self.GetSelectionData() def rerender_col(self, col): for infohash, lr in self.itemData_to_row.iteritems(): HashableListView.InsertRow(self, infohash, lr, sort=False, force_update_columns=[col]) def update_torrent(self, torrent_object): state = (torrent_object.state, torrent_object.policy, torrent_object.completed) eta = torrent_object.statistics.get('timeEst' , None) up_rate = torrent_object.statistics.get('upRate' , None) down_rate = torrent_object.statistics.get('downRate', None) peers = torrent_object.statistics.get('numPeers', None) row = self.GetRowFromKey(torrent_object.infohash) ur = Rate(up_rate) if (torrent_object.completion < 1.0) or (down_rate > 0): dr = Rate(down_rate) else: dr = Rate() eta = Duration(eta) priority = frontend_priority[torrent_object.priority] lr = BTListRow(None, {'state': state, 'name': row['name'], 'progress': percentify(torrent_object.completion, torrent_object.completed), 'eta': eta, 'urate': ur, 'drate': dr, 'priority': priority, 'peers': peers}) HashableListView.InsertRow(self, torrent_object.infohash, lr, sort=False) if not self.columns['progress'].enabled: return try: completion = float(completion) except: completion = 0.0 # FIXME -- holy crap, re-factor so we don't have to repaint gauges here if row.index >= len(self.gauges): self._gauge_paint() gauge = self.gauges[row.index] gauge.SetValue(torrent_object.completion, torrent_object.state, torrent_object.piece_states) def get_column_image(self, row): value = row['state'] imageindex = self.image_list_offset if value is not None: imageindex += image_numbers[state_images[value]] # Don't overflow the image list, even if we get a wacky state return min(imageindex, len(image_names)+self.image_list_offset)VERBOSE = Falseclass PeerListView(HashableListView): def __init__(self, torrent, *a, **k): self.columns = {'ip': BTListColumn(_('IP address'), '255.255.255.255', comparator=ip_sort), 'client': BTListColumn(_('Client'), # extra .0 needed to make it just a little wider 'BitTorrent 5.0.0.0', renderer=unicode), 'id': BTListColumn(_('Peer id'), 'M5-0-0--888888888888', renderer=lambda v: repr(v)[1:-1], enabled=VERBOSE), 'initiation': BTListColumn(_('Initiation'), 'remote'), 'down_rate': BTListColumn(_('KB/s down'), Rate(1024**2 - 1)), 'up_rate': BTListColumn(_('KB/s up'), Rate(1024**2 - 1)), 'down_size': BTListColumn(_('MB downloaded'), Size(1024**3 - 1)), 'up_size': BTListColumn(_('MB uploaded'), Size(1024**3 - 1)), 'completed': BTListColumn(_('% complete'), 1.0, renderer=lambda v: '%.1f'%round(int(v*1000)/10, 1)), 'speed': BTListColumn(_('KB/s est. peer download'), Rate(1024**2 - 1)), 'total_eta': BTListColumn(_('est. peer total ETA'), Duration(1700000), enabled=VERBOSE), } self.column_order = ['ip', 'id', 'client', 'completed', 'down_rate', 'up_rate', 'down_size', 'up_size', 'speed', 'initiation', 'total_eta'] HashableListView.__init__(self, *a, **k) self.torrent = torrent # add BT logo # wx.Image under wx 2.6.2 doesn't like to load ICO files this way: ##i = wx.Image(os.path.join(image_root, 'bittorrent.ico'), ## type=wx.BITMAP_TYPE_ICO, index=4) i = wx.Image(os.path.join(image_root, 'logo', 'bittorrent_icon_16.png'), type=wx.BITMAP_TYPE_PNG) b = wx.BitmapFromImage(i) assert b.Ok(), "The image (%s) is not valid." % name self.il.Add(b) # add flags self.image_list_offset = self.il.GetImageCount() flag_images = os.listdir(os.path.join(image_root, 'flags')) flag_images.sort() self.cc_index = {} image_library = wx.the_app.image_library for f in flag_images: try: f = f[:f.rindex('.')] # grab everything before the last '.' except: pass # unless there is no last '.' if len(f) == 2 or f in ('unknown', 'noimage'): name = ('flags', f) i = self.add_image(image_library.get(name)) self.cc_index[f] = i self.set_default_widths() self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu) def OnContextMenu(self, event): m = wx.Menu() id = wx.NewId() m.Append(id, _("Add Peer")) self.Bind(wx.EVT_MENU, self.AddPeer, id=id) self.PopupMenu(m) def AddPeer(self, event): text = wx.GetTextFromUser(_("Enter new peer in IP:port format"), _("Add Peer")) try: ip, port = text.split(':') ip = str(ip) port = int(port) except: return self.torrent.torrent._connection_manager.start_connection((ip, port), None) def update_peers(self, peers, bad_peers): old_peers = set(self.itemData_to_row.keys()) for peer in peers: peerid = peer['id'] data = {} for k in ('ip', 'completed', 'id',): data[k] = peer[k] client, version = ClientIdentifier.identify_client(peerid) data['client'] = client + ' ' + version # ew! #data['initiation'] = peer['initiation'] == 'R' and _("remote") or _("local") if peer['initiation'].startswith('R'): data['initiation'] = _("remote") else: data['initiation'] = _("local") dl = peer['download'] ul = peer['upload'] data['down_rate'] = Rate(dl[1], precision=1024) data['up_rate' ] = Rate(ul[1], precision=1024) data['down_size'] = Size(dl[0], precision=1024**2) data['up_size' ] = Size(ul[0], precision=1024**2) data['speed'] = Rate(peer['speed']) if 'total_eta' in peer: data['total_eta'] = Duration(peer['total_eta']) else: data['total_eta'] = '' colour = None they_interested, they_choke, they_snub = dl[2:5] me_interested, me_choke = ul[2:4] strength = sum((not they_interested, they_choke, they_snub, not me_interested, me_choke, not peer['is_optimistic_unchoke']))/6 c = int(192 * strength) colour = wx.Colour(c, c, c) if peer['ip'] in bad_peers: bad, perip = bad_peers[peer['ip']] if perip.peerid == peer['id']: # color bad peers red colour = wx.RED lr = BTListRow(None, data) self.InsertRow(peerid, lr, sort=False, colour=colour) old_peers.discard(peerid) for old_peer in old_peers: self.DeleteRow(old_peer) if len(old_peers) > 0: # force a background erase, since the number of items has decreased self.OnEraseBackground() self.SortItems() def get_column_image(self, row): ip_address = row['ip'] # BitTorrent seeds if ip_address.startswith('38.114.167.') and \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -