import os, sys import threading from time 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,gobject.TYPE_STRING)), } 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 # remove unfinished sumlist from collection self.collection.rem_sumlist(unicode(self.thread.uri)) self.thread = None def _progress_fn(self, walkthread, c, l, r, currentlyScanning): # only emit if called from the current request if walkthread == self.thread: gtk.gdk.threads_enter() self.emit("progress", c, l, currentlyScanning) 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 self.progresstimer = 0 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) if recursionlvl <= 1: self.__check_progress() return result def run(self): """ Parse the root directory """ self.progresstimer = time() self.result = SumList(self.__uri_tail(self.uri), None, 0) self.master._progress_fn(self, 0, 1, self.result, self.uri) # write some debug information starttime = 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 # walk the subdirectories self.progress_total = len(subdirectories) self.progress_count = 0 for self.directory in subdirectories: sub = self.build_tree_gnomevfs(self.uri.append_path(self.directory)) self.result.append_child( sub ) if self.stopsignal: return self.progress_count += 1 # emit final signal self.master._finished_fn(self,self.result) self.master.collection.set_sumlist(unicode(self.uri),self.result) print "finished walking",self.uri,"(time=%s)"%round(time()-starttime,2) def __check_progress(self): if time()-self.progresstimer > .25: self.progresstimer = time() #self.result.sort_by_size() self.master._progress_fn(self, self.progress_count, self.progress_total, self.result, self.directory) 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 "Could not open",uri,"(not a valid uri)" except NotFoundError: print "Could not open",uri,"(not found)" except AccessDeniedError: print "Could not open",uri,"(access denied)"