import os, sys import threading import time import gobject, gtk import posixpath from gnomevfs import * from fringdata import * class FringWalker( gobject.GObject ): """ Manages requests for walking folder hierarchies. Folder data is stored in SumList objects. """ __gsignals__ = { 'list-changed': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)), 'finished': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)), 'manually-stopped': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, () ), 'progress': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_INT,gobject.TYPE_INT)), } def __init__(self, sumlistcollection): gobject.GObject.__init__(self) self.thread = None self.showhidden = True self.collection = sumlistcollection def walk(self,uri): self.stop() self.thread = WalkThread(self,uri,self.showhidden) self.thread.start() def stop(self): if self.thread: self.emit("manually-stopped") self.thread.stopsignal = True self.thread = None def _progress_fn(self, walkthread, c, l, r): # only emit if called from the current request if walkthread == self.thread: gtk.gdk.threads_enter() self.emit("progress", c, l) self.emit("list-changed", r) gtk.gdk.threads_leave() def _finished_fn(self, walkthread, r): if walkthread == self.thread: gtk.gdk.threads_enter() self.emit("finished", r) gtk.gdk.threads_leave() self.thread = None class WalkThread( threading.Thread ): """ A separate class for the thread. Aggregated by FringWalker. """ def __init__(self, master, uri, showhidden): """ Parameters: A FringWalker instance, a string with the path and a bool """ threading.Thread.__init__(self) self.stopsignal = False self.master = master self.uri = URI(uri) self.showhidden = showhidden self.max_recursion_sort = 3 def build_tree_gnomevfs(self, uri, recursionlvl=0): result = SumList(self.__uri_tail(uri), None, 0) h = self.__open_directory(uri) if h is None: return result try: while True: if self.stopsignal: return result d = h.next() if not self.showhidden and d.name[0] == ".": continue if d.name == "." or d.name == "..": continue if d.type == 2: result.append_child( self.build_tree_gnomevfs(uri.append_path(d.name),recursionlvl+1) ) else: result.append_child( SumList(d.name, None, d.size) ) except StopIteration: pass if recursionlvl <= self.max_recursion_sort: result.sort_by_size() self.master.collection.set_sumlist(unicode(uri),result) return result def run(self): """ Parse the root directory """ self.result = SumList(self.__uri_tail(self.uri), None, 0) # write some debug information starttime = time.time() print "start walking",self.uri # scan root directory first (using gnomevfs) h = self.__open_directory(self.uri) if h is None: return subdirectories = [] try: while True: if self.stopsignal: return d = h.next() if not self.showhidden and d.name[0] == ".": continue if d.name == "." or d.name == "..": continue if d.type == 2: subdirectories.append( d.name ); else: self.result.append_child( SumList(d.name, None, d.size) ) except StopIteration: pass # emit an intermediate version to fill up the screen while waiting self.result.sort() self.master.collection.set_sumlist(unicode(self.uri),self.result) self.master._progress_fn(self, 0, len(subdirectories), self.result) # walk the subdirectories c = 0 for directory in subdirectories: c += 1 self.result.append_child( self.build_tree_gnomevfs(self.uri.append_path(directory)) ) if self.stopsignal: return self.result.sort() self.master.collection.set_sumlist(unicode(self.uri),self.result) self.master._progress_fn(self, c, len(subdirectories), self.result) # emit final signal self.master._finished_fn(self,self.result) print "finished walking",self.uri,"(time=%s)"%round(time.time()-starttime,2) def __uri_tail(self, uri): """ Return the tail (the filename) of a gnomevfs uri """ f = format_uri_for_display(str(uri)) f = posixpath.split( f )[-1] return f def __open_directory(self, uri): try: return DirectoryHandle(uri) except InvalidURIError: print uri,"is not a valid uri, skipped" except NotFoundError: print uri,"not found, skipped"