From e39436576c68e70ac70d4ee108860d411b52d0bb Mon Sep 17 00:00:00 2001 From: Frederic Back Date: Wed, 27 Sep 2006 17:19:35 +0000 Subject: * added gnomevfs support * added menu entry to choose walking method * merged back from trunk * UI now uses gnomevfs everywhere git-svn-id: file:///home/lennart/svn/public/fring/branches/c_walker@33 d0d2c35f-0a1e-0410-abeb-dabff30a67ee --- src/fringlib/fringrenderer.py | 51 ++++++++++---------- src/fringlib/fringui.py | 50 ++++++++++++------- src/fringlib/fringutil.py | 12 +++++ src/fringlib/fringwalker.py | 109 +++++++++++++++++++++++++++++++++++++----- src/fringlib/launch.py | 7 ++- 5 files changed, 175 insertions(+), 54 deletions(-) diff --git a/src/fringlib/fringrenderer.py b/src/fringlib/fringrenderer.py index f69a0a2..0f71f8a 100644 --- a/src/fringlib/fringrenderer.py +++ b/src/fringlib/fringrenderer.py @@ -1,10 +1,8 @@ import cairo import pango from math import * -#from fringwalker import sum_list from fringutil import * import os -from fringwalker import print_tree class Hotspot: @@ -55,8 +53,8 @@ class FringRenderer: if data is None: return dataname = data[0] - datadata = data[1] - datathe_sum = data[2] + datacontents = data[1] + datasize = data[2] if ring == 0: self.lookup_data = [] @@ -68,27 +66,24 @@ class FringRenderer: CENTERX, CENTERY = self.WIDTH/2, self.HEIGHT/2 ctx.move_to(CENTERX, CENTERY) - if ring == 0: - self._draw_centered_text(ctx, pretty_size(datathe_sum)) - - n = len(datadata) + n = len(datacontents) i = 0 accumulated = 0 last = start_angle - if datadata is None: return - for fn, contents, d in datadata: + if datacontents is None: return + for fn, contents, d in datacontents: + if contents == None: hasContents = False else: hasContents = True start = last - value = d # third tuple element now *always* contains the size - accumulated += value - - end = start_angle+(end_angle - start_angle)*1.0*accumulated/datathe_sum + + if datasize == 0: continue + end = start_angle+(end_angle - start_angle)*1.0*accumulated/datasize if end-start >= .01: @@ -159,17 +154,27 @@ class FringRenderer: width *= -1 self.__register_side_link(hasContents,p,value,end-start,x,y+(height/2),x+(width),y-(height/2)) - - if ring <= self.LABEL_UNTIL_RING: + + # write disk usage on segments + if self.RING_RADIUS >= ctx.text_extents("55%")[3]: ctx.move_to(*middle) 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_text(ctx, "%.0f%%" %percent) - # write relative and absolute disk usage - self._draw_centered_text2(ctx, "%.0f%%" % ((end-start)*100), pretty_size(value)) - last = end i += 1 + if ring == 0: + ctx.set_source_rgb(.3,.3,.3) + i = format_disk_space(datasize) + ctx.move_to(CENTERX, CENTERY) + width,height = self._draw_centered_text(ctx, i[0], .5, 1 ) + ctx.move_to(CENTERX, CENTERY+height) + self._draw_centered_text(ctx, i[1], .5, 1 ) + def get_hotspot_at(self,x,y): for h in self.side_links: if x >= h.minx and x <= h.maxx and \ @@ -202,7 +207,9 @@ class FringRenderer: p = int(maxidx*v) # Initial estimation while True: - d = data[p] + + try: d = data[p] + except IndexError: return None if v <= d.start: maxidx = p-1 @@ -244,10 +251,6 @@ class FringRenderer: (t,p,v), (v,p,q))[int(h)] - def _list_value(self,l): - if isinstance(l, sum_list): - return l.the_sum - return l def _choose_color(self,v, ring): color = self.hsv2rgb(v, .61, 1-ring*0.1) diff --git a/src/fringlib/fringui.py b/src/fringlib/fringui.py index 5236af6..ffe624c 100644 --- a/src/fringlib/fringui.py +++ b/src/fringlib/fringui.py @@ -3,7 +3,7 @@ import cairo import sys import os -from fringwalker import FringWalker +from fringwalker import * from fringrenderer import FringRenderer from fringutil import * @@ -37,6 +37,14 @@ ui = """ + + + + + + + + @@ -56,7 +64,7 @@ ui = """ class UI( gtk.Window ): - def __init__(self, path): + def __init__(self, uri): self.busy_cursor = 0 self.backgroundColour = (1,1,1) self.data = None @@ -67,14 +75,15 @@ class UI( gtk.Window ): # create gui gtk.Window.__init__(self) self.set_title("fring"); - self.__init_gui(path) + self.__init_gui() # walk directory self.walker.connect("list-changed",self.__list_changed) self.walker.connect("finished", self.__walker_finished) - self.open_folder(path) + self.walker.connect("manually-stopped", lambda w: self.__show_busy_cursor(-1)) + self.open_folder(uri) - def __init_gui(self, path): + def __init_gui(self): # create menubar uimanager = gtk.UIManager() @@ -82,6 +91,7 @@ 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"), @@ -95,8 +105,18 @@ class UI( gtk.Window ): ('About', gtk.STOCK_ABOUT, "_About", None, "About", self.about_dialog), ]) action = gtk.ToggleAction("Show Hidden Files", "Show Hidden Files", None, None) + 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), + ], 0) + 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') @@ -113,7 +133,8 @@ class UI( gtk.Window ): b = gtk.FileChooserButton('Select a Folder') b.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) - b.connect("current-folder-changed", lambda w: self.__set_path(w.get_current_folder())) + + b.connect("current-folder-changed", lambda w: self.__set_path(w.get_uri())) toolbar.pack_start( b, True ) self.filechooserbutton = b @@ -155,12 +176,9 @@ class UI( gtk.Window ): self.eventbox.connect("size-allocate",self.__on_resize) self.connect("delete_event", self.close) - - - def open_folder(self,path): - print "open",path + def open_folder(self,uri): # change folder by changing the chooser button - self.filechooserbutton.set_current_folder(path) + self.filechooserbutton.set_current_folder_uri(uri) def about_dialog(self,widget): d = gtk.AboutDialog() @@ -197,15 +215,11 @@ class UI( gtk.Window ): if not self.data: return self.renderer.WIDTH = self.width self.renderer.HEIGHT = self.height - self.renderer.INNER_RADIUS = self.height/15 + self.renderer.INNER_RADIUS = self.height/12 self.renderer.RING_RADIUS = self.height/10 #self.renderer.INNER_RADIUS *= self.zoomfactor self.renderer.RING_RADIUS *= self.zoomfactor self.renderer.RINGS_MAX = 3 - - self.renderer.LABEL_UNTIL_RING = int(self.zoomfactor - 0.4) - if self.zoomfactor < 0.8: self.renderer.LABEL_UNTIL_RING = -1 - self.renderer.draw_segment(self.ctx, 0, 0, 1, 0, 1, self.data, self.path) self.image.queue_draw() self.__show_busy_cursor(-1) @@ -234,7 +248,7 @@ class UI( gtk.Window ): self.path = path self.walker.stop() if path is None: return - self.walker.walk(path); + self.walker.walk(path,self.methodaction.get_current_value()) self.__show_busy_cursor(1) def __selectfolder(self,widget): @@ -242,7 +256,7 @@ class UI( gtk.Window ): d = gtk.FileChooserDialog(None, self, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_CANCEL,0,gtk.STOCK_OK,1)) - if d.run() == 1: self.open_folder(d.get_current_folder()) + if d.run() == 1: self.open_folder(d.get_uri()) d.destroy() def __hidden_files_toggled(self,widget): diff --git a/src/fringlib/fringutil.py b/src/fringlib/fringutil.py index e174d66..4bfa5d7 100644 --- a/src/fringlib/fringutil.py +++ b/src/fringlib/fringutil.py @@ -10,3 +10,15 @@ def pretty_size(size): return "%u B" % size +def format_disk_space(size): + """ Convert bytes to a human readable format. + Returns a tuple, for example (20,"MiB") """ + + if size >= 1024*1024*1024: + return ("%.1f"%round(size/1024/1024/1024.0),"GiB") + elif size >= 1024*1024: + return ("%.1f"%round(size/1024/1024.0),"MiB") + elif size >= 1024: + return ("%.1f"%round(size/1024.0),"KiB") + else: + return ("%u"%size,"B") diff --git a/src/fringlib/fringwalker.py b/src/fringlib/fringwalker.py index 99eaeff..364b997 100644 --- a/src/fringlib/fringwalker.py +++ b/src/fringlib/fringwalker.py @@ -1,12 +1,21 @@ import os, os.path, stat, sys -import gobject, gtk -from threading import Thread +import threading +import posixpath # instead of os.path for gnomevfs operations import time + +import gobject, gtk +from gnomevfs import * + import fringtools +WALKER_CLASSIC = 0 +WALKER_GNOMEVFS = 1 +WALKER_CPP = 2 + 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 @@ -55,13 +64,17 @@ class FringWalker( gobject.GObject ): self.thread = None self.showhidden = False - def walk(self,path): + def walk(self,uri,method=WALKER_GNOMEVFS): self.stop() - self.thread = WalkThread(self,path,self.showhidden) + + print "walkwalk",uri + + self.thread = WalkThread(self,uri,self.showhidden,method) self.thread.start() def stop(self): if self.thread: + self.emit("manually-stopped") self.thread.stopsignal = True self.thread = None @@ -78,23 +91,90 @@ class FringWalker( gobject.GObject ): gtk.gdk.threads_enter() self.emit("finished", r) gtk.gdk.threads_leave() + self.thread = None -class WalkThread( Thread ): +class WalkThread( threading.Thread ): """ A separate class for the thread. """ - def __init__(self, master, path, showhidden): + + def __init__(self, master, uri, showhidden, method=WALKER_CLASSIC): """ Parameters: A FringWalker instance, a string with the path and a bool """ - Thread.__init__(self) + threading.Thread.__init__(self) self.stopsignal = False self.master = master - self.path = path + self.uri = uri self.showhidden = showhidden + self.method = method + + print "open",uri + self.path = get_local_path_from_uri( str(uri) ) + print "local",self.path + + + def build_tree_python(self, path, showhidden): + l = [] + total = 0 + for fn in os.listdir(path): + if self.stopsignal: return (None,None,0) + if not 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,showhidden) + 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 __uri_tail(self, uri): + """ Return the filename in a gnomevfs uri """ + f = format_uri_for_display(str(uri)) + f = posixpath.split( f )[-1] + return f + + def build_tree_gnomevfs(self, uri, showhidden): + + try: h = DirectoryHandle(uri) + except InvalidURIError: + print uri,"is not a valid uri, skipped" + return (str(uri), None, 0) + except NotFoundError: + print uri,"not found, skipped" + return (str(uri), None, 0) + + l = [] + total = 0 + d = h.next() + try: + while True: + if self.stopsignal: return (None,None,0) + d = h.next() + if not showhidden and d.name[0] == ".": continue + + if d.type == 2: # directory + sub = self.build_tree_gnomevfs(uri.append_path(d.name),showhidden) + l.append( sub ) + total += sub[2] + else: + l.append( (d.name, None, d.size) ) + total += d.size + + except StopIteration: pass + return (self.__uri_tail(uri), l, total) + def run(self): """ Parse the root directory """ - print "start walking",self.path + starttime = time.time() + print "start walking",self.path, + if self.method == WALKER_CPP: print "(using c++ extension)" + elif self.method == WALKER_GNOMEVFS: print "(using python and gnomevfs)" + else: print "(using classic python)" l = [] i = 0 @@ -136,7 +216,13 @@ class WalkThread( Thread ): for fn, p in subdirectories: c += 1 - sub = fringtools.build_tree(p, self.showhidden) + if self.method == WALKER_CPP: + sub = fringtools.build_tree(p, self.showhidden) + elif self.method == WALKER_GNOMEVFS: + sub = self.build_tree_gnomevfs(URI("file://"+p), self.showhidden) + else: + sub = self.build_tree_python(p, self.showhidden) + if self.stopsignal: return None total += sub[2] @@ -154,4 +240,5 @@ class WalkThread( Thread ): # emit final signal self.master._finished_fn(self,(os.path.split(self.path)[-1], l, total)) - print "finished walking",self.path + print "finished walking",self.path,"(time=%s)"%round(time.time()-starttime,2) + diff --git a/src/fringlib/launch.py b/src/fringlib/launch.py index 8e3b107..f420768 100755 --- a/src/fringlib/launch.py +++ b/src/fringlib/launch.py @@ -17,11 +17,12 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. -# Copyright Lennart Poettering, 2006 +# Copyright Lennart Poettering, Frederic Back 2006 import sys, os import gtk import fringui +import gnomevfs if __name__ == "__main__": @@ -30,6 +31,10 @@ if __name__ == "__main__": else: tree_path = os.path.expanduser("~") + # first parameter can be a gnomevfs uri or a local path + #try: uri = URI(tree_path) + #except: uri = get_uri_from_local_path(tree_path) + ui = fringui.UI(tree_path) gtk.gdk.threads_init() -- cgit