From 4dae0aaa6d348b7961c3620e0ded88d560aef4af Mon Sep 17 00:00:00 2001 From: Frederic Back Date: Mon, 2 Oct 2006 12:59:27 +0000 Subject: * Added SumList as a dummy class again to be able to create pointers to subfolders. This will allow fast switching to subfolders. * Removed all walkers except the gnomevfs one * Added status message when hovering parent button git-svn-id: file:///home/lennart/svn/public/fring/trunk@51 d0d2c35f-0a1e-0410-abeb-dabff30a67ee --- src/fringlib/fringrenderer.py | 57 +++++++++++++------------ src/fringlib/fringui.py | 78 +++++++++++++++++----------------- src/fringlib/fringwalker.py | 97 ++++++++++++++++++------------------------- 3 files changed, 107 insertions(+), 125 deletions(-) diff --git a/src/fringlib/fringrenderer.py b/src/fringlib/fringrenderer.py index c5fd5ee..59ea2a3 100644 --- a/src/fringlib/fringrenderer.py +++ b/src/fringlib/fringrenderer.py @@ -6,26 +6,29 @@ import os class Hotspot: - def __init__(self, is_dir, path, size, value): + def __init__(self, is_dir, path, sumlist, value): self.is_dir = is_dir self.path = path - self.size = size + self.sumlist = sumlist self.value = value self.percentage = value*100 + class SideLink(Hotspot): - def __init__(self, is_dir, path, size, value, minpos, maxpos): - Hotspot.__init__(self, is_dir, path, size, value) + def __init__(self, is_dir, path, sumlist, value, minpos, maxpos): + Hotspot.__init__(self, is_dir, path, sumlist, value) self.minx,self.miny = minpos self.maxx,self.maxy = maxpos + class Segment(Hotspot): - def __init__(self, is_dir, path, size, start, end): - Hotspot.__init__(self, is_dir, path, size, end-start) + def __init__(self, is_dir, path, sumlist, start, end): + Hotspot.__init__(self, is_dir, path, sumlist, end-start) self.start, self.end = start, end + class FringRenderer: @@ -59,13 +62,8 @@ class FringRenderer: self.linklayout.set_font_description(pango.FontDescription("sans 8")) def draw_segment(self,ctx, ring, start_angle, end_angle, start_hue, end_hue, data, previouspath=""): - if data is None: return - dataname = data[0] - datacontents = data[1] - datasize = data[2] - if ring == 0: self.lookup_data = [] self.side_links = [] @@ -76,27 +74,26 @@ class FringRenderer: CENTERX, CENTERY = self.WIDTH/2, self.HEIGHT/2 ctx.move_to(CENTERX, CENTERY) - n = len(datacontents) + n = len(data.children) i = 0 accumulated = 0 last = start_angle - for entry in datacontents: - fn, contents, value = entry + for entry in data.children: - hasContents = contents != None + hasContents = entry.children != None start = last - accumulated += value + accumulated += entry.size - if datasize == 0: continue - end = start_angle+(end_angle - start_angle)*1.0*accumulated/datasize + if data.size == 0: continue + end = start_angle+(end_angle - start_angle)*1.0*accumulated/data.size if end-start >= .005: - p = previouspath+os.sep+fn - self.lookup_data[ring].append( Segment(hasContents , p, value, start, end) ) + p = previouspath+os.sep+entry.name + self.lookup_data[ring].append( Segment(hasContents , p, entry, start, end) ) color = self._choose_color(start_hue + (end_hue-start_hue)*1.0*i/n, ring) @@ -117,7 +114,7 @@ class FringRenderer: self.draw_segment(ctx, ring+1, start, end, start_hue + (end_hue-start_hue)*1.0*i/n, start_hue + (end_hue-start_hue)*1.0*(i+1)/n, entry, - previouspath+os.sep+fn) + previouspath+os.sep+entry.name) r += self.RING_RADIUS/2 middle = CENTERX+r*cos((start+end)*pi), CENTERY+r*sin((start+end)*pi) @@ -149,12 +146,18 @@ class FringRenderer: else: ctx.set_source_rgb(*self.FILE_LABEL_COLOR) # todo: cut down label size if longer than WIDTH/2 - ring*ringradius - innerradius - label = fn + label = entry.name width,height = self._draw_centered_text(ctx, label, align_x) if align_x == 0: width *= -1 #TODO change this... - self.__register_side_link(hasContents,p,value,end-start,x,y+(height/2),x+(width),y-(height/2)) + + self.__register_side_link( + hasContents, + p, + entry, + end-start, + x,y+(height/2),x+(width),y-(height/2)) # draw line ctx.move_to(*point_a) @@ -172,7 +175,7 @@ class FringRenderer: ctx.set_source_rgb(0, 0, 0) percent = (end-start)*100 if percent >= 8: - #self._draw_centered_text2(ctx, "%.0f%%" % ((end-start)*100), pretty_size(value)) + #self._draw_centered_text2(ctx, "%.0f%%" % ((end-start)*100), pretty_size(entry.size)) self._draw_centered_text(ctx, "%.0f%%" %percent) last = end @@ -180,7 +183,7 @@ class FringRenderer: if ring == 0: ctx.set_source_rgb(.3,.3,.3) - i = format_disk_space(datasize) + i = format_disk_space(data.size) ctx.move_to(CENTERX, CENTERY) width,height = self._draw_centered_text(ctx, i[0], .5, 1 ) ctx.move_to(CENTERX, CENTERY+height) @@ -239,10 +242,10 @@ class FringRenderer: p = np # Funny! - def __register_side_link(self,is_dir,path,size,value,x0,y0,x1,y1): + def __register_side_link(self,is_dir,path,sumlist,value,x0,y0,x1,y1): if x1 < x0: x0,x1 = x1,x0 # swap if y1 < y0: y0,y1 = y1,y0 - self.side_links.append(SideLink(is_dir, path, size, value, (x0,y0), (x1,y1))) + self.side_links.append(SideLink(is_dir, path, sumlist, value, (x0,y0), (x1,y1))) def hsv2rgb(self,h,s,v): if s<=0: diff --git a/src/fringlib/fringui.py b/src/fringlib/fringui.py index a6c606d..068fd97 100644 --- a/src/fringlib/fringui.py +++ b/src/fringlib/fringui.py @@ -37,14 +37,6 @@ ui = """ - - - - - - - - @@ -71,6 +63,7 @@ class UI( gtk.Window ): self.zoomfactor = 1.0 self.renderer = FringRenderer() self.walker = FringWalker(); + self.scan_active = False # create gui gtk.Window.__init__(self) @@ -91,7 +84,6 @@ class UI( gtk.Window ): self.add_accel_group(accelgroup) ag_global = gtk.ActionGroup('ag_global') ag_global.add_actions([ - ('TreeWalker', None, "TreeWalker"), ('FRing', None, "_Folder"), ('View', None, "_View"), ('Help', None, "_Help"), @@ -108,15 +100,6 @@ class UI( gtk.Window ): action.set_active(True) action.connect("toggled",self.__hidden_files_toggled) ag_global.add_action(action) - - # add a menu with radio buttons to choose the walking method - ag_global.add_radio_actions([ - ('Python', None, "Python", None, None, WALKER_CLASSIC), - ('Python gnomevfs', None, "Python gnomevfs", None, None, WALKER_GNOMEVFS), - ('c++', None, "c++", None, None, WALKER_CPP), - ], 1) - self.methodaction = ag_global.get_action("c++") - uimanager.insert_action_group(ag_global, 0) uimanager.add_ui_from_string(ui) menubar = uimanager.get_widget('/MenuBar') @@ -130,6 +113,8 @@ class UI( gtk.Window ): b.set_property("image", img) uimanager.get_action("/MenuBar/FRing/OpenParent").connect_proxy(b) toolbar.pack_start( b, False ) + b.connect("enter-notify-event",self.__enter_parent_button) + b.connect("leave-notify-event",self.__leave_parent_button) b = gtk.FileChooserButton('Select a Folder') b.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) @@ -194,9 +179,7 @@ class UI( gtk.Window ): gtk.main_quit() def open_parent(self,widget): - p = os.path.split(self.uri) - p = os.path.join(p[:-1]) - self.open_folder(p[0]) + self.open_folder(self.__get_parent(self.uri)) def zoom(self,widget,factor): self.zoomfactor += factor @@ -242,12 +225,19 @@ class UI( gtk.Window ): #----------------------------------------------------------- private methods + def __get_parent(self,uri): + """ Get the parent folder from an uri """ + p = os.path.split(uri) + p = os.path.join(p[:-1]) + return p[0] + def __set_uri(self,uri): """ Set a path and start parsing. Also used to refresh or reset. """ self.uri = uri self.walker.stop() if uri: - self.walker.walk(uri,self.methodaction.get_current_value()) + self.walker.walk(uri) + self.scan_active = True self.__show_busy_cursor(1) def __selectfolder(self,widget): @@ -263,27 +253,30 @@ class UI( gtk.Window ): self.walker.showhidden = widget.get_active() self.__set_uri(self.uri) - def __move_event(self, widget, event): - + def __move_event(self, widget, event): f = self.renderer.get_hotspot_at(event.x, event.y) - if f is None: - self.label.set_text("Ready.") - else: - self.label.set_markup("Path %s, %s, %0.1f%%" % (f.path, pretty_size(f.size), f.value*100)) + self.label.set_text("") + if f: + + markup = "%s, %s, %0.1f%%" % (f.path, pretty_size(f.sumlist.size), f.value*100) + self.label.set_markup(markup) - if f is None or not f.is_dir: - if self.busy_cursor > 0: cursor = gtk.gdk.Cursor(gtk.gdk.WATCH) - else: cursor = None - self.eventbox.window.set_cursor(cursor) - else: - # always display a hand when hovering a link - self.eventbox.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND1)) + if f.sumlist.children is not None: + self.eventbox.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND1)) + return + + self.eventbox.window.set_cursor(None) def __click_event(self, widget, event): f = self.renderer.get_hotspot_at(event.x, event.y) - if f is not None: - if f.is_dir: - self.open_folder(f.path) + if f and f.sumlist.children: + + #if self.scan_active: + # if we are still walking the tree, start a new scan on the path + self.__set_uri(f.path) + #else: + # if we are sure that the sumlist is complete, jump there directly + #self.__list_changed(None,f.sumlist) def __scroll_event(self, widget, event): if event.direction is gtk.gdk.SCROLL_UP: @@ -306,11 +299,11 @@ class UI( gtk.Window ): def __list_changed(self,widget,data): self.data = data self.redraw() - #print data.name def __walker_finished(self, widget, data): self.__list_changed(widget, data) self.__show_busy_cursor(-1) + self.scan_active = False def __on_resize(self, widget, event): r = self.eventbox.get_allocation() @@ -321,13 +314,16 @@ class UI( gtk.Window ): def __show_busy_cursor(self, value): if self.busy_cursor <= 0 and self.busy_cursor+value >= 0: if self.window: self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) - self.label.set_markup("Busy...") elif self.busy_cursor > 0 and self.busy_cursor+value <= 0: if self.window: self.window.set_cursor(None) - self.label.set_text("Ready.") self.busy_cursor += value #print "busy state:",self.busy_cursor + def __enter_parent_button(self,widget,event): + markup = "%s" %self.__get_parent(self.uri) + self.label.set_markup(markup) + def __leave_parent_button(self,widget,event): + self.label.set_markup("") diff --git a/src/fringlib/fringwalker.py b/src/fringlib/fringwalker.py index d897123..cede5af 100644 --- a/src/fringlib/fringwalker.py +++ b/src/fringlib/fringwalker.py @@ -7,25 +7,38 @@ import gobject, gtk from gnomevfs import * try: import fringtools -except: print 'Error: Could not find "fringtools" extension module' +except: pass -WALKER_CLASSIC = 0 -WALKER_GNOMEVFS = 1 -WALKER_CPP = 2 +class SumList: + + def __init__(self, name, children, size): + self.name = name + self.children = children + self.size = size + + def __getitem__(self, key): + if key == 0: return self.name + if key == 1: return self.children + if key == 2: return self.size + + def __len__(self): + return 3 -def print_tree( treearray, tab=0 ): + +def print_tree( sumlist, 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 + print " "*tab,"%s (%i)"%(sumlist.name,sumlist.size) + if not sumlist.children: return if tab > 1: return - for e in data: + for e in sumlist.children: print_tree(e,tab+1) + def treearray_cmp_by_size( b, a ): return cmp(a[2], b[2]) # compare sizes + def treearray_cmp_fn( b, a ): """ a and b are tuples describing a directory tree. Compare first by directory status, then by size, and finally by name. """ @@ -66,9 +79,9 @@ class FringWalker( gobject.GObject ): self.thread = None self.showhidden = False - def walk(self,uri,method=WALKER_GNOMEVFS): + def walk(self,uri): self.stop() - self.thread = WalkThread(self,uri,self.showhidden,method) + self.thread = WalkThread(self,uri,self.showhidden) self.thread.start() def stop(self): @@ -97,14 +110,13 @@ class WalkThread( threading.Thread ): """ A separate class for the thread. """ - def __init__(self, master, uri, showhidden, method=WALKER_CLASSIC): + 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.method = method self.max_recursion_sort = 3 @@ -114,24 +126,6 @@ class WalkThread( threading.Thread ): f = posixpath.split( f )[-1] return f - def build_tree_python(self, path): - l = [] - total = 0 - for fn in os.listdir(path): - if self.stopsignal: return (None,None,0) - if not self.showhidden and fn[0] == ".": continue - try: p = os.path.join(path, fn) - except: continue - s = os.lstat(p) - if stat.S_ISDIR(s.st_mode): - sub = self.build_tree_python(p) - l.append( sub ) - total += sub[2] - elif stat.S_ISREG(s.st_mode): - l.append( (fn, None, s.st_size) ) - total += s.st_size - return (os.path.split(path)[-1], l, total) - def build_tree_gnomevfs(self, uri, recursionlvl=0): @@ -156,14 +150,14 @@ class WalkThread( threading.Thread ): l.append( sub ) total += sub[2] else: - l.append( (d.name, None, d.size) ) + l.append( SumList(d.name, None, d.size) ) total += d.size except StopIteration: pass if recursionlvl <= self.max_recursion_sort: l.sort(treearray_cmp_by_size) - return (self.__uri_tail(uri), l, total) + return SumList(self.__uri_tail(uri), l, total) def run(self): @@ -172,9 +166,6 @@ class WalkThread( threading.Thread ): # write some debug information starttime = time.time() print "start walking",self.uri, - if self.method == WALKER_CPP: print "(using c++ extension)" - elif self.method == WALKER_GNOMEVFS: print "(using python and gnomevfs)" - else: print "(using classic python)" # scan root directory first (using gnomevfs) try: h = DirectoryHandle(self.uri) @@ -197,47 +188,39 @@ class WalkThread( threading.Thread ): if d.type == 2: # directory subdirectories.append( d.name ); else: - l.append( (d.name, None, d.size) ) + l.append( SumList(d.name, None, d.size) ) total += d.size except StopIteration: pass # emit an intermediate version to fill up the screen while waiting - self.master._progress_fn(self, - 0, len(subdirectories), - (self.__uri_tail(self.uri), l, total)) + sumlist = SumList(self.__uri_tail(self.uri), l, total) + self.master._progress_fn(self, 0, len(subdirectories), sumlist) - # now walk the subdirectories with the faster extension function + # walk the subdirectories c = 0 - for directory in subdirectories: c += 1 - if self.method == WALKER_CPP: - path = get_local_path_from_uri(str(self.uri))+os.sep+directory - sub = fringtools.build_tree(path, self.showhidden) - elif self.method == WALKER_GNOMEVFS: - uri = self.uri - sub = self.build_tree_gnomevfs(uri.append_path(directory)) - else: - path = get_local_path_from_uri(str(self.uri))+os.sep+directory - sub = self.build_tree_python(path) + uri = self.uri + sub = self.build_tree_gnomevfs(uri.append_path(directory)) if self.stopsignal: return - total += sub[2] - l.append( (directory,sub[1],sub[2]) ); + total += sub.size + sub.name = directory + l.append( sub ); l.sort(treearray_cmp_fn) # emit an intermediate version after each directory - self.master._progress_fn(self, - c, len(subdirectories), - (self.__uri_tail(self.uri), l, total)) + sumlist = SumList(self.__uri_tail(self.uri), l, total) + self.master._progress_fn(self, c, len(subdirectories), sumlist) l.sort(treearray_cmp_fn) # emit final signal - self.master._finished_fn(self,(self.__uri_tail(self.uri), l, total)) + sumlist = SumList(self.__uri_tail(self.uri), l, total) + self.master._finished_fn(self,sumlist) print "finished walking",self.uri,"(time=%s)"%round(time.time()-starttime,2) -- cgit