summaryrefslogtreecommitdiffstats
path: root/src/fringlib/fringwalker.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/fringlib/fringwalker.py')
-rw-r--r--src/fringlib/fringwalker.py140
1 files changed, 93 insertions, 47 deletions
diff --git a/src/fringlib/fringwalker.py b/src/fringlib/fringwalker.py
index 5137306..99eaeff 100644
--- a/src/fringlib/fringwalker.py
+++ b/src/fringlib/fringwalker.py
@@ -5,107 +5,153 @@ import time
import fringtools
-def print_tree( t, tab=0 ):
- """ An utility function to print out the tree returned by FringWalker::_parse """
-
- fn, data, size = t
+def print_tree( treearray, tab=0 ):
+ """ An utility function to print out a tree array """
+ fn, data, size = treearray
print " "*tab,"%s (%i)"%(fn,size)
if not data: return
+ if tab > 1: return
for e in data:
print_tree(e,tab+1)
+
+def treearray_cmp_fn( a, b ):
+ """ a and b are tuples describing a directory tree. Compare first by directory
+ status, then by size, and finally by name. """
+
+ a_dir = a[1] != None
+ b_dir = b[1] != None
+
+ if a_dir and not b_dir:
+ return 1
+ elif b_dir and not a_dir:
+ return -1
+ elif a_dir and b_dir:
+ return cmp(a[2], b[2]) # compare sizes
+ else:
+ return cmp(a[0], b[0]) # compare names
+
+
class FringWalker( gobject.GObject ):
+ """ Manages requests for walking directories
+
+ Directory entries are represented by tuples of the following form:
+ (name, contents, size)
+
+ name: the file name of the directory
+ contents: a list of entries within the entry. If None, the entry is not a directory
+ size: the size of the entry.
+ """
__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):
gobject.GObject.__init__(self)
self.thread = None
- self.stopsignal = False
self.showhidden = False
-
def walk(self,path):
- self.thread = Thread(None,self._parse,None,(path,))
- self.stopsignal = False
- print "start thread (%s)"%path
+ self.stop()
+ self.thread = WalkThread(self,path,self.showhidden)
self.thread.start()
-
def stop(self):
- if self.thread is None:
- return
-
- if not self.thread.isAlive():
+ if self.thread:
+ self.thread.stopsignal = True
self.thread = None
- return
- self.stopsignal = True
- print "stopping thread:"
- #self.thread.join()
- print "ok"
+ 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()
- def _parse(self,path):
+
+class WalkThread( Thread ):
+ """ A separate class for the thread. """
+
+ def __init__(self, master, path, showhidden):
+ """ Parameters: A FringWalker instance, a string with the path and a bool """
+ Thread.__init__(self)
+ self.stopsignal = False
+ self.master = master
+ self.path = path
+ self.showhidden = showhidden
+
+ def run(self):
""" Parse the root directory """
+ print "start walking",self.path
+
l = []
i = 0
- subdirectories = {}
-
+ subdirectories = []
total = 0
+ # make a first run for the root directory
try:
- for fn in os.listdir(path):
+ for fn in os.listdir(self.path):
+
+ if self.stopsignal: return None
if not self.showhidden and fn[0] == '.': continue
- try: p = os.path.join(path, fn)
+ try: p = os.path.join(self.path, fn)
except: continue
s = os.lstat(p)
if stat.S_ISDIR(s.st_mode):
- subdirectories[i] = (fn,p);
- l.append((fn, None, s.st_size))
+ subdirectories.append( (fn,p) );
elif stat.S_ISREG(s.st_mode):
l.append((fn, None, s.st_size))
total += s.st_size
i += 1
- except:
+ except OSError:
pass
+
+ # emit an intermediate version to fill up the screen while waiting
+ self.master._progress_fn(self,
+ 0, len(subdirectories),
+ (os.path.split(self.path)[-1], l, total))
- gtk.gdk.threads_enter()
- self.emit("list-changed",(os.path.split(path)[-1], l, total))
- gtk.gdk.threads_leave()
-
+ # now walk the subdirectories with the faster extension function
c = 0
- for n in subdirectories:
+
+ for fn, p in subdirectories:
c += 1
- fn,p = subdirectories[n]
- sub = fringtools.build_tree(p,True) # call faster c++ extension
+ sub = fringtools.build_tree(p, self.showhidden)
+ if self.stopsignal: return None
+
total += sub[2]
-
- l[n] = (fn,sub[1],sub[2]);
+ l.append( (fn,sub[1],sub[2]) );
- if self.stopsignal: return
+ l.sort(treearray_cmp_fn)
- # emit signals
- gtk.gdk.threads_enter()
- self.emit("list-changed",(os.path.split(path)[-1], l, total))
- print "%s parsed"%fn
- gtk.gdk.threads_leave()
+ # emit an intermediate version after each directory
+ self.master._progress_fn(self,
+ c, len(subdirectories),
+ (os.path.split(self.path)[-1], l, total))
+
+ l.sort(treearray_cmp_fn)
- gtk.gdk.threads_enter()
- self.emit("finished",(os.path.split(path)[-1], l, total))
- gtk.gdk.threads_leave()
-
- print "finished walking",path
+ # emit final signal
+ self.master._finished_fn(self,(os.path.split(self.path)[-1], l, total))
+ print "finished walking",self.path