First working PAC version
[findit] / src / files / outdiagram.py
index b309dca..b333057 100755 (executable)
@@ -2,87 +2,91 @@
 # -*-coding: utf-8 -*-
 # vim: sw=4 ts=4 expandtab ai
 
-import gtk
-import gobject
-from random import randint
+from random import random
+from math import pi, cos, sin, sqrt
+import os.path
 
+#==============================================================================
 
-class Control(object):
-    def __init__(self, config):
-        win_width = config.get('window_width')
-        win_height = config.get('window_height')
-        self.out_ui = Out_Diag_Presentation(win_width, win_height)
-
-    def show(self, filelist, fullsize):
-        self.out_ui.get_data(filelist, fullsize)
-
-    def run(self):
-        self.out_ui.run()
-
-
-class Abstraction(object):
+class Cli_Presentation(object):
     pass
 
+#==============================================================================
 
 class Gtk_Presentation(object):
+    def __init__(self, filelist, maxdata=10):
+        import gtk
+        import cairo
 
-    def __init__(self):
-
-        self.area = gtk.DrawingArea()
-        self.area.set_size_request(250, 200) ###
-        self.area.set_events(gtk.gdk.POINTER_MOTION_MASK |
-                             gtk.gdk.POINTER_MOTION_HINT_MASK )
-        self.area.connect('expose-event', self.expose_event)
-        self.pixmap = None
-
-    def expose_event(self, widget, event):
-        if not self.pixmap:
-            self.build_pixmap()
-        x, y, width, height = event.area
-        widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL],
-                                    self.pixmap, x, y, x, y, width, height)
-        return False
-
-    def build_pixmap(self):
-        #self.pixmap = gtk.gdk.Pixmap(self.window, self.width, self.height)
-        self.pixmap = gtk.gdk.Pixmap(None, 250, 200, 8) ###
-        cm = self.pixmap.get_colormap()
-        self.color = {}
-        self.color['black'] = cm.alloc_color('black')
-        self.color['white'] = cm.alloc_color('white')
-        self.gc = self.pixmap.new_gc()
-        self.gc.set_foreground(self.color['white'])
-        self.pixmap.draw_rectangle(self.gc, True, 0, 0, self.width, self.height)
-
-    def draw_diag(self):
-        start_angle = 0
-        for path, size, bsize in self.filelist:
-            end_angle = (bsize*360*64)/self.fullsize
-            print start_angle, end_angle
-            gc = self.pixmap.new_gc()
-            cm = self.pixmap.get_colormap()
-            col1 = cm.alloc_color(self.rand_color())
-            gc.set_foreground(col1)
-            gc.set_line_attributes(1,gtk.gdk.LINE_SOLID,gtk.gdk.CAP_NOT_LAST,gtk.gdk.JOIN_MITER)
-            self.pixmap.draw_arc(gc, True, 0, 0, self.width, self.height, start_angle, end_angle)
-            start_angle = start_angle + end_angle
-        self.area.queue_draw()
+        drawing = gtk.DrawingArea()
 
-    def rand_color(self):
-        r = randint(0, 65535)
-        g = randint(0, 65535)
-        b = randint(0, 65535)
-        return gtk.gdk.Color(r, g, b, 0)
+        # `maxdata` biggest files from list
+        filelist.sort(reverse=True)
+        del filelist[maxdata:]
+        self.filelist = filelist
 
-    def run(self):
-        self.show_all()
-        gobject.timeout_add(1000, self.draw_diag)
-        gtk.main()
+        # sum of sizes
+        fullsize = sum((f[0] for f in filelist))
 
-    def get_data(self, filelist, fullsize):
-        self.filelist = filelist
-        self.fullsize = fullsize
+        # sectors list
+        sectors = []
+        start_angle = 0
+        for bsize, name, size in filelist:
+            color = self.rand_color()
+            delta_angle = (float(bsize)/fullsize)*2*pi
+            end_angle = start_angle + delta_angle
+            color = self.rand_color()
+            sectors.append((start_angle, end_angle, color))
+            start_angle += delta_angle
+
+        drawing.connect('expose-event', self.expose_event, sectors)
+
+        self.toplevel = drawing
+
+    def expose_event(self, widget, event, sectors):
+        x, y, w, h, _ = widget.window.get_geometry()
+        R = min(w-w/3, h)/2 - 20
+
+        cr = widget.window.cairo_create()   # cairo context
+        cr.translate(w/2-w/6, h/2)          # moving coordinates
+
+        # drawing pie chart
+        for i, (start_angle, end_angle, color) in enumerate(sectors):
+            # drawing sector
+            cr.move_to(0, 0)
+            cr.set_source_rgb(*color)
+            cr.arc(0, 0, R, start_angle, end_angle)
+            cr.fill()
+
+            # to cartesian coordinates
+            delta_angle = end_angle - start_angle
+            x = R/1.7 * cos(start_angle+delta_angle/2)
+            y = R/1.7 * sin(start_angle+delta_angle/2)
+            area = 0.5*(delta_angle*R**2)   # sector area
+
+            # drawing text
+            cr.set_font_size(sqrt(area)/3)  # text size
+            text = str(i+1)                 # text string
+            xbearing, ybearing, textw, texth = cr.text_extents(text)[:4]
+            cr.move_to(x-(xbearing+textw/2), y-(ybearing+texth/2))  # text center
+            cr.set_source_rgb(.3, .3, .3)   # text color
+            cr.show_text(text)
+
+        cr.set_font_size(14)
+        cr.translate(w/2-w/6, -h/2+40)  # moving coordinates
+        cr.move_to(0, 0)
+
+        # drawing files list
+        for i, (bsize, name, size) in enumerate(self.filelist):
+            color = sectors[i][2]
+            cr.set_source_rgb(*color)
+            cr.rectangle(-20, 20*i+3, 14, -14)
+            cr.fill()
+
+            text = str(i+1) + '. ' + os.path.basename(name) + ' (' + str(size) + ')'
+            cr.move_to(0, 20*i)
+            cr.set_source_rgb(0, 0, 0)
+            cr.show_text(text)
 
-    #=== Toplevel widget for embedding to search area =========================
-    def get_toplevel(self):
-        return self.area
+    def rand_color(self):
+        return random(), random(), random()