Python source code for the BitTorrent Property Page for Nautilus project. Back to the project page »
#!/usr/bin/python # Copyright (C) 2004 Paul Sowden # This code is released under the terms of the LGPL import gtk, gobject, urllib, time import nautilus import BitTorrent.bencode from types import * COL_NAME = 0 COL_SIZE = 1 class BTPropertyPage(nautilus.PropertyPageProvider): def __init__(self): pass def get_property_pages(self, files): if len(files) != 1: return file = files[0] if file.get_uri_scheme() != 'file': return if not file.is_mime_type('application/x-bittorrent'): return filename = urllib.unquote(file.get_uri()[7:]) torrent_file = open(filename).read(0x200000) # < 2 MB torrent_info = BitTorrent.bencode.bdecode(torrent_file) self.property_label = gtk.Label('BitTorrent') self.property_label.show() self.vbox = gtk.VBox(False, 12) self.vbox.set_border_width(12) info = [] info.append(('Tracker URL', torrent_info['announce'])) # optional fields if torrent_info.has_key('created by'): info.append(('Created By', torrent_info['created by'])) if torrent_info.has_key('creation date'): info.append(('Created On', self.format_date(torrent_info['creation date']))) if torrent_info.has_key('comment'): info.append(('Comment', torrent_info['comment'])) self.vbox.pack_start( self.create_frame('Info', self.create_info_table(info)), False, False) # d/l consists of multiple files if torrent_info['info'].has_key('files'): files = [] totalsize = 0 for file in torrent_info['info']['files']: fileloc = files if len(file['path']) > 1: for dir in file['path'][:-1]: for entry in fileloc: if entry[0] == dir: fileloc = entry[1] break else: fileloc.append((dir, [])) fileloc = fileloc[-1][1] fileloc.append((file['path'][-1], file['length'])) totalsize += file['length'] store = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_INT) for file in files: self.populate_treestore(store, None, file) treeview, scrollview = self.create_treeview(store) fileinfo = [] fileinfo.append(('Suggested Folder', torrent_info['info']['name'])) fileinfo.append(('Total Size', self.format_size(totalsize))) #fileinfo.append(('# Pieces', torrent_info['info']['piece length'])) vbox = gtk.VBox(False, 12) vbox.pack_start(self.create_info_table(fileinfo), False, False) vbox.pack_start(scrollview) self.vbox.pack_start(self.create_frame('Files', vbox, 1.0, 1.0)) else: fileinfo = [] fileinfo.append(('Suggested Name', torrent_info['info']['name'])) fileinfo.append(('Size', self.format_size(torrent_info['info']['length']))) #fileinfo.append(('# Pieces', torrent_info['info']['piece length'])) # optional fields if torrent_info['info'].has_key('md5sum'): fileinfo.append(('MD5 Checksum', torrent_info['info']['md5sum'])) self.vbox.pack_start(self.create_frame('File', self.create_info_table(fileinfo))) self.vbox.show_all() return nautilus.PropertyPage("NautilusPython::bittorrent", self.property_label, self.vbox), def format_size(self, size): if size < 1024: return '%d B' % size elif size < 1048576: return '%.1f KiB' % (size / 1024.0) elif size < 1073741824: return '%.1f MiB' % (size / 1048576.0) else: return '%.1f GiB' % (size / 1073741824.0) def format_date(self, datetime): return time.strftime('%A, %B %d %Y at %H:%M:%S', time.localtime(datetime)) def populate_treestore(self, store, parentiter, entry): childiter = store.insert_before(parentiter, None) store.set_value(childiter, COL_NAME, entry[0]) if type(entry[1]) is ListType: # directory store.set_value(childiter, COL_SIZE, len(entry[1])) for childentry in entry[1]: self.populate_treestore(store, childiter, childentry) else: #file store.set_value(childiter, COL_SIZE, entry[1]) def size_cell_data_function (self, column, cell, model, iter, user_data=None): size = model.get_value(iter, COL_SIZE) if model.iter_has_child(iter): text = '%d items' % size else: text = self.format_size(size) cell.set_property('text', text) def create_treeview(self, model): treeview = gtk.TreeView(model) # first column renderer = gtk.CellRendererText() column = gtk.TreeViewColumn("File", renderer, text=COL_NAME) treeview.append_column(column) # second column renderer = gtk.CellRendererText() renderer.set_property('xalign', 1.0) column = gtk.TreeViewColumn("Size", renderer, text=COL_SIZE) column.set_cell_data_func(renderer, self.size_cell_data_function) treeview.append_column(column) # Create scrollbars around the view. scrolled = gtk.ScrolledWindow() scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scrolled.add(treeview) return treeview, scrolled def create_frame(self, labeltext, view, xscale=0.0, yscale=0.0): frame = gtk.Frame() frame.set_shadow_type(gtk.SHADOW_NONE) label = gtk.Label() label.set_use_markup(True) label.set_markup('<b>%s</b>' % labeltext) frame.set_label_widget(label) alignment = gtk.Alignment(xscale=xscale, yscale=yscale) alignment.set_padding(0, 0, 12, 0) alignment.add(view) view.set_border_width(6) frame.add(alignment) return frame def create_info_table(self, rows): table = gtk.Table(rows=len(rows), columns=2) table.set_row_spacings(6) table.set_col_spacings(12) i = 0 for row in rows: label = gtk.Label('%s:' % row[0]) alignment = gtk.Alignment() alignment.add(label) table.attach(alignment, 0, 1, i, i+1, gtk.FILL) data = gtk.Label(row[1]) alignment = gtk.Alignment() alignment.add(data) table.attach(alignment, 1, 2, i, i+1, gtk.FILL) i += 1 return table