#!/usr/bin/env python import dircache import pygtk pygtk.require ('2.0') import gtk import gobject import os import os.path import stat def make_stock_menu_item_factory_param (stock_item, path = "", callback = None, param = 0, type = None): (stock_id, label, modifier, keyval, translation_domain) = gtk.stock_lookup (stock_item) return (path + label, gtk.accelerator_name (keyval, modifier), callback, param, type); class Player: def __init__ (self): self.name = 'Unknown' self.mount_point = None self.subdirectory = "" self.replace_illegals = True class FileSet: class Entry: def __init__ (self, name): self.name = name def get_name (self): return self.name def intersect (self, other): return None def minus (self, other): return None class File (Entry): def __init__ (self, name, path): super (name) self.path = path self.size = None self.mtime = None self.data = None def do_init (self): if self.path: stat = stat (path) self.size = stat.ST_SIZE self.mtime = stat.ST_MTIME self.path = None def get_size (self): self.do_init () return self.size def get_mtime (self): self.do_init () return self.mtime def __eq__ (self, other): if isinstance (other, File): self.do_init () other.do_init () if self.name == other.name and \ self.size == other.size and \ self.mtime == other.mtime: return True return False def __ne__ (self, other): return not self.__eq__ (other) def intersect (self, other): if self == other: return self else: return None def minus (self, other): if self == other: return None else: return self class Directory (Entry): def __init__ (self, name, path): super (name) self.path = path self.entries = None self.data = None def do_init (self): if self.path: self.entries = [] def entry_cmp (x, y): ret = cmp (x, y) if ret == 0: ret = cmp (x.lower (), y.lower ()) return ret for entry in sorted (dircache.listdir (path, entry_cmp)): self.entries.append (read_entry (entry, os.path.join (path, entry))) self.path = None def get_entries (self): self.do_init () return self.entries def intersect (self, other): if isinstance (other, Directory): self.do_init () other.do_init () ret = Dictionary (self.name, None) ret.entries = [] self_index = 0 other_index = 0 while self_start < len (self.entries) and other_start < len (other.entries): cmp_result = cmp (self.entries[self_index].name, other.entries[other_index].name) if cmp_result < 0: self_index = self_index + 1 elif cmp_result > 0: other_index = other_index + 1 else: ret.entries.append (self.entries[self_index].intersect (other.entries[other_index])) return ret else: return None def minus (self, other): if isinstance (other, Directory): self.do_init () other.do_init () ret = Dictionary (self.name, None) ret.entries = [] self_index = 0 other_index = 0 while self_start < len (self.entries) and other_start < len (other.entries): cmp_result = cmp (self.entries[self_index].name, other.entries[other_index].name) if cmp_result != 0: ret.entries.append (self.entries[self_index]) if cmp_result < 0: self_index = self_index + 1 elif cmp_result > 0: other_index = other_index + 1 return ret else: return self def __init__ (self, root_path): self.root_path = root_path self.root_entry = None def read_entry (name, path): stat = os.stat (path) if stat.S_ISDIR (path): return Directory (name, path) elif stat.S_ISREG (path): return File (name, path) def refresh (self, callback): if self.root_path: self.root_entry = read_entry (None, self.root_path) def intersect (self, other): ret = FileSet (None) if self.root_entry and other.root_entry: ret.root_entry = self.root_entry.intersect (other.root_entry.intersect) return ret def minus (self, other): ret = FileSet (None) if self.root_entry: if other.root_entry: ret.root_entry = self.root_entry.minus (other.root_entry) else: ret.root_entry = self.root_entry return ret class TreeModel (gtk.GenericTreeModel): column_types = (str, gobject.TYPE_BOOLEAN, object) def __init__ (self, fileset = None): self.fileset = fileset self.marked = set () def on_get_flags (self): return gtk.TREE_MODEL_ITERS_PERSIST def on_get_n_columns (self): return len (self.column_types); def on_get_column_type (self, index): return self.column_types[index] def on_get_iter (self, path): ret = [] current_entry = self.fileset.root_entry for index in path: current_entry = current_entry.entries[index] ret.append (current_entry.name) return ret def follow_rowref (self, rowref, proc): dir_entry = self.fileset.root_entry for rowref_index in range (0, len (rowref)): index = 0 while index < len (dir_entry.entries): test_entry = dir_entry.entries[index] if test_entry.name == rowref[rowref_index]: proc (dir_entry.entries, index, rowref_index) dir_entry = test_entry break index = index + 1 if index == len (dir_entry.entries): return False return True def on_get_path (self, rowref): class on_get_path_follow_rowref_proc: def __init__ (self): ret = [] def __call__ (self, entries, index, rowref_index): self.ret.append (index) proc = on_get_path_follow_rowref_proc () if self.follow_rowref (rowref, proc): return tuple (proc.ret) else: return None def on_get_value (self, rowref, column): if column == 0: if len (rowref) == 0: return None else: return rowref[-1] elif column == 1: return rowref in self.marks elif column == 2: class on_get_value_follow_rowref_proc: def __init__ (self, rowref): self.ret = None self.rowref_len = len (rowref) def __call__ (self, entries, index, rowref_index): if rowref_index == (self.rowref_len - 1): self.ret = entries[index] if rowref == None: return self.root_entry proc = on_get_value_follow_rowref_proc (rowref) if self.follow_rowref (rowref, proc): return proc.ret else: return None else: return None def on_iter_next (self, rowref): class on_iter_next_follow_rowref_proc: def __init__ (self, rowref): self.rowref_len = len (rowref) self.ret = [] def __call__ (self, entries, index, rowref_index): if rowref_index == (self.rowref_len - 1): if (index < (len (entries) - 1)): self.ret.append (entries[index + 1].name) else: self.ret = None else: self.ret.append (entries[index]) proc = on_iter_next_follow_rowref_proc (rowref) if self.follow_rowref (rowref, proc): return tuple (proc.ret) else: return None def on_iter_children (self, parent): entry = self.on_iter_get_value (parent, 2) if isinstance (entry, Directory): return entry.entries[0] else: return None def on_iter_has_child (self, rowref): entry = self.on_iter_get_value (rowref, 2) if isinstance (entry, Directory): return len (entry.entries) != 0 else: return False def on_iter_n_children (self, rowref): entry = self.on_iter_get_value (rowref, 2) if isinstance (entry, Directory): return len (entry.entries) else: return 0 def on_iter_nth_child (self, parent, n): if parent == None: return self.root_entry.entries[n] else: entry = self.on_iter_get_value (rowref, 2) if isinstance (entry, Directory) and \ (n < len (entry.entries)): return entry.entries[n] else: return None def on_iter_parent (self, child): if child == None: return None elif len (child) < 2: return None else: return child[0:-1] class MainWindow (gtk.Window): def __init__ (self): gtk.Window.__init__ (self, gtk.WINDOW_TOPLEVEL) self.accel_group = gtk.AccelGroup () self.add_accel_group (self.accel_group) self.item_factory = gtk.ItemFactory (gtk.MenuBar, "
", self.accel_group) menu_items = ( ("/_File", None, None, 0, "", ), make_stock_menu_item_factory_param (gtk.STOCK_APPLY, "/_Apply/", self.apply_clicked), make_stock_menu_item_factory_param (gtk.STOCK_QUIT, "/_Quit/", self.quit), ("/_Help", None, None, 0, "", ), make_stock_menu_item_factory_param (gtk.STOCK_ABOUT, "/_About/", self.about_clicked) ) self.item_factory.create_items (menu_items) menubar = self.item_factory.get_widget ("
") vbox = gtk.VBox (False, 0) vbox.pack_start (menubar, False, True, 0) menubar.show () self.treemodel = TreeModel (FileSet (".")) self.treeview = gtk.TreeView (self.treemodel) self.toggle_renderer = gtk.CellRendererToggle () self.text_renderer = gtk.CellRendererText () self.treeview_column = gtk.TreeViewColumn.pack_start (self.toggle_renderer, False) self.treeview_column = gtk.TreeViewColumn.pack_start (self.text_renderer, True) self.treeview_column.add_attribute (self.toggle_renderer, "active", 2) self.treeview_column.add_attribute (self.text_renderer, "text", 1) vbox.pack_start (self.treeview, True, True) self.treeview.show () self.add (vbox) vbox.show () self.show () def apply_clicked (self, widget, data): pass def quit (self, widget, data): pass def about_clicked (self, widget, data): pass main_window = MainWindow ()