summaryrefslogtreecommitdiffstats
path: root/src/fringlib/fringui.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/fringlib/fringui.py')
-rw-r--r--src/fringlib/fringui.py276
1 files changed, 276 insertions, 0 deletions
diff --git a/src/fringlib/fringui.py b/src/fringlib/fringui.py
new file mode 100644
index 0000000..f6e231b
--- /dev/null
+++ b/src/fringlib/fringui.py
@@ -0,0 +1,276 @@
+import gtk
+import cairo
+import sys
+import os
+
+from fringwalker import FringWalker
+from fringrenderer import FringRenderer
+
+GPL = """
+fring is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+fring is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with fring; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA.
+"""
+
+ui = """
+<ui>
+
+ <menubar name="MenuBar">
+ <menu action="FRing">
+ <menuitem action="SelectFolder"/>
+ <menuitem action="OpenParent"/>
+ <menuitem action="Refresh"/>
+ <separator />
+ <menuitem action="Save Image..."/>
+ <separator />
+ <menuitem action="Quit"/>
+ </menu>
+ <menu action="View">
+ <menuitem action="Show Hidden Files"/>
+ <separator />
+ <menuitem action="Zoom In"/>
+ <menuitem action="Zoom Out"/>
+ </menu>
+ <menu action="Help">
+ <menuitem action="About"/>
+ </menu>
+ </menubar>
+
+ <toolbar name="Toolbar">
+ </toolbar>
+
+</ui>"""
+
+
+class UI( gtk.Window ):
+
+ def __init__(self, path):
+ self.backgroundColour = (1,1,1)
+ self.data = None
+ self.zoomfactor = 1.0
+ self.renderer = FringRenderer()
+ self.walker = FringWalker();
+
+ # create gui
+ gtk.Window.__init__(self)
+ self.set_title("fring");
+ self.__init_gui(path)
+
+ # walk directory
+ self.walker.connect("list-changed",self.__list_changed)
+ self.open_folder(path)
+
+
+ def __init_gui(self, path):
+
+ # create menubar
+ uimanager = gtk.UIManager()
+ accelgroup = uimanager.get_accel_group()
+ self.add_accel_group(accelgroup)
+ ag_global = gtk.ActionGroup('ag_global')
+ ag_global.add_actions([
+ ('FRing', None, "_Folder"),
+ ('View', None, "_View"),
+ ('Help', None, "_Help"),
+ ('OpenParent', gtk.STOCK_GO_UP, "Open _Parent", "<alt>Up", "Open the parent folder", self.open_parent),
+ ('SelectFolder', gtk.STOCK_OPEN, "_Open Folder...", None, "Open Folder...", self.__selectfolder),
+ ('Quit', gtk.STOCK_QUIT, "_Quit", None, "Quit", self.close),
+ ('Zoom In', gtk.STOCK_ZOOM_IN, "Zoom _In", "<ctrl>Up", "Zoom In", lambda w: self.zoom(w,0.2)),
+ ('Zoom Out', gtk.STOCK_ZOOM_OUT, "Zoom _Out", "<ctrl>Down", "Zoom Out", lambda w: self.zoom(w,-0.2)),
+ ('Save Image...', gtk.STOCK_SAVE_AS, "_Save Image...", None, "Save Image...", self.save_image),
+ ('Refresh', gtk.STOCK_REFRESH, "_Refresh Tree", "<ctrl>R", "Refresh Tree", lambda w: self.__set_path(self.path)),
+ ('About', gtk.STOCK_ABOUT, "_About", None, "About", self.about_dialog),
+ ])
+ action = gtk.ToggleAction("Show Hidden Files", "Show Hidden Files", None, None)
+ action.connect("toggled",self.__hidden_files_toggled)
+ ag_global.add_action(action)
+ uimanager.insert_action_group(ag_global, 0)
+ uimanager.add_ui_from_string(ui)
+ menubar = uimanager.get_widget('/MenuBar')
+ menubar.show()
+
+ # create toolbar
+ toolbar = gtk.HBox()
+
+ b = gtk.Button()
+ img = gtk.image_new_from_stock(gtk.STOCK_GO_UP, gtk.ICON_SIZE_BUTTON)
+ b.set_property("image", img)
+ uimanager.get_action("/MenuBar/FRing/OpenParent").connect_proxy(b)
+ toolbar.pack_start( b, False )
+
+ 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()))
+ toolbar.pack_start( b, True )
+ self.filechooserbutton = b
+
+ # create canvas
+ self.eventbox = gtk.EventBox()
+ self.image = gtk.Image()
+ self.eventbox.add(self.image)
+ self.eventbox.add_events( gtk.gdk.EXPOSURE_MASK
+ | gtk.gdk.LEAVE_NOTIFY_MASK
+ | gtk.gdk.BUTTON_PRESS_MASK
+ | gtk.gdk.POINTER_MOTION_MASK )
+ self.eventbox.connect("scroll_event", self.__scroll_event)
+ self.eventbox.connect("button-press-event",self.__click_event)
+ self.eventbox.connect("motion-notify-event",self.__move_event)
+
+ # aligh menubar, toolbar and canvas vertically
+ vbox = gtk.VBox();
+ vbox.pack_start(menubar,False,False)
+ vbox.pack_start(toolbar,False,False)
+ f = gtk.Frame()
+ f.set_shadow_type(gtk.SHADOW_IN)
+ f.add(self.eventbox)
+ vbox.pack_start(f)
+ self.add(vbox)
+
+ # show everything
+ # Note: With set_default_size, the image can't be downsized.
+ self.set_size_request(100,100) # minimum size, needed!
+ self.resize(500,350)
+ self.show_all()
+ self.__create_canvas()
+ self.eventbox.connect("size-allocate",self.__on_resize)
+ self.connect("delete_event", self.close)
+
+ def open_folder(self,path):
+ print "open",path
+ # change folder by changing the chooser button
+ self.filechooserbutton.set_current_folder(path)
+
+ def about_dialog(self,widget):
+ d = gtk.AboutDialog()
+ d.set_name("fring");
+ d.set_license(GPL);
+ d.set_copyright("copyright 2006 Lennart Poettering, Frederic Back")
+ d.run()
+ d.destroy()
+
+ def close(self,w=None,e=None):
+ self.walker.stop()
+ self.destroy()
+ gtk.main_quit()
+
+ def open_parent(self,widget):
+ p = os.path.split(self.path)
+ p = os.path.join(p[:-1])
+ self.open_folder(p[0])
+
+ def zoom(self,widget,factor):
+ self.zoomfactor += factor
+ if self.zoomfactor < 0:
+ self.zoomfactor = 0
+ self.redraw()
+
+ def redraw(self,widget=None):
+ # clear the canvas
+ self.ctx.rectangle(0,0,self.width,self.height)
+ self.ctx.set_source_rgb(*self.backgroundColour)
+ self.ctx.fill()
+
+ # draw segments
+ if not self.data: return
+ self.renderer.WIDTH = self.width
+ self.renderer.HEIGHT = self.height
+ self.renderer.INNER_RADIUS = self.height/15
+ 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.hotspots = []
+ self.renderer.draw_segment(self.ctx, 0, 0, 1, 0, 1, self.data, self.path)
+ self.image.queue_draw()
+
+ def save_image(self, widget=None):
+ d = gtk.FileChooserDialog("Save As...",
+ self.get_toplevel(), gtk.FILE_CHOOSER_ACTION_SAVE,
+ (gtk.STOCK_CANCEL,0,gtk.STOCK_OK,1), None)
+ d.set_current_name( self.data.name.replace(" ","_") + ".png" )
+ r = d.run()
+ if r == 1:
+ #print d.get_uri()
+ pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,True,8,self.width,self.height)
+ pixmap, mask = self.image.get_pixmap()
+ pixbuf.get_from_drawable(pixmap,pixmap.get_colormap(),0,0,0,0,-1,-1)
+ #pixbuf.save(d.get_filename(), "jpeg", {"quality":"100"})
+ pixbuf.save(d.get_filename(), "png", {})
+ d.destroy()
+
+ #----------------------------------------------------------- private methods
+
+ def __set_path(self,path):
+ """ Set a path and start parsing. Also used to refresh or reset. """
+ self.path = path
+ self.walker.stop()
+ if path is None: return
+ self.walker.walk(path);
+
+ def __selectfolder(self,widget):
+ """ Open a dialog to select a folder """
+ 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())
+ d.destroy()
+
+ def __hidden_files_toggled(self,widget):
+ if self.walker.showhidden == widget.get_active(): return
+ self.walker.showhidden = widget.get_active()
+ self.__set_path(self.path)
+
+ def __move_event(self, widget, event):
+ f = self.renderer.get_hotspot_at(event.x, event.y)
+ if f is None:
+ self.eventbox.window.set_cursor(None) #gtk.gdk.Cursor(gtk.gdk.CROSSHAIR))
+ else:
+ self.eventbox.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND1))
+
+ def __click_event(self, widget, event):
+ f = self.renderer.get_hotspot_at(event.x, event.y)
+ if f is not None: self.open_folder(f)
+
+ def __scroll_event(self, widget, event):
+ if event.direction is gtk.gdk.SCROLL_UP:
+ self.zoom(widget, 0.2)
+ elif event.direction is gtk.gdk.SCROLL_DOWN:
+ self.zoom(widget, -0.2)
+
+ def __create_canvas(self):
+ # create a new pixmap and cairo context
+ r = self.eventbox.get_allocation()
+ self.width, self.height = r.width, r.height
+ self.pixmap = gtk.gdk.Pixmap(self.window,r.width,r.height)
+ self.image.set_from_pixmap(self.pixmap,None)
+ self.ctx = self.pixmap.cairo_create()
+ self.renderer.prepare_layouts(self.ctx)
+
+ def __list_changed(self,widget,data):
+ self.data = data
+ self.redraw()
+ #print data.name
+
+ def __on_resize(self, widget, event):
+ r = self.eventbox.get_allocation()
+ if (r.width,r.height) != (self.width,self.height):
+ self.__create_canvas()
+ self.redraw()
+
+
+