just removing the gtk-image-missing...
[cascardo/movie.git] / gzv.py
diff --git a/gzv.py b/gzv.py
index 2d5c926..14e0a2b 100644 (file)
--- a/gzv.py
+++ b/gzv.py
@@ -15,6 +15,7 @@
 import os
 import gtk
 import gtk.glade
+import gobject
 import math
 import cairo
 from ConfigParser import ConfigParser
@@ -26,9 +27,9 @@ class Ball(object):
 
     def __init__(self, x, y, r, name='', position=0):
         self.position = position
-        self.x = x
-        self.y = y
-        self.radios = r
+        self.x = int(x)
+        self.y = int(y)
+        self.radius = int(r)
         self.name = name
 
 class BallManager(list):
@@ -38,7 +39,7 @@ class BallManager(list):
     def save_to_file(self, path):
         target = open(path, 'w')
         for i in self:
-            target.write('%d,%d %d %s\n' % (i.x, i.y, i.radios, i.name))
+            target.write('%d,%d %d %s\n' % (i.x, i.y, i.radius, i.name))
         target.close()
 
 class GladeLoader(object):
@@ -76,10 +77,14 @@ class Project(object):
         self.focus_points_file = ''
 
     def save_to_file(self, path):
-        bn = os.path.basename(path)
-        name = os.path.splitext(bn)[0]
+        if not self.focus_points_file:
+            bn = os.path.basename(path)
+            name = os.path.splitext(bn)[0]
+            self.focus_points_file = \
+                os.path.join(os.path.dirname(path), name + '_fpf')
 
         cp = ConfigParser()
+        cp.add_section('Project')
         cp.set('Project', 'image', self.image)
         cp.set('Project', 'width', self.width)
         cp.set('Project', 'height', self.height)
@@ -110,6 +115,9 @@ class NewProject(GladeLoader):
             self.dialog.set_transient_for(parent)
 
     def get_project(self):
+        if not self.dialog.run():
+            return None
+
         fname = self.wid('image').get_filename()
         width = self.wid('width').get_text()
         height = self.wid('height').get_text()
@@ -134,7 +142,7 @@ class Gzv(GladeLoader):
         self.treeview.set_model(self.model)
 
         self.draw = self.wid('draw')
-        self.draw.connect('expose-event', self.expose_draw)
+        self.draw.connect_after('expose-event', self.expose_draw)
 
         # Starting with an empty project with no image loaded
         self.project = None
@@ -147,10 +155,10 @@ class Gzv(GladeLoader):
         self.setup_treeview()
 
         # drawing stuff
-        self.ball_width = Ball.DEFAULT_WIDTH
         self.selecting = False
         self.start_x = -1
         self.start_y = -1
+        self.radius = Ball.DEFAULT_WIDTH
 
     def setup_treeview(self):
         self.model.connect('rows-reordered', self.on_rows_reordered)
@@ -163,22 +171,24 @@ class Gzv(GladeLoader):
         renderer = gtk.CellRendererText()
         renderer.connect('edited', self.on_cell_edited)
         renderer.set_property('editable', True)
-        column = gtk.TreeViewColumn(_('Name'), renderer, text=1)
-        self.treeview.append_column(column)
+        self.fpcolumn = gtk.TreeViewColumn(_('Name'), renderer, text=1)
+        self.treeview.append_column(self.fpcolumn)
 
     def on_rows_reordered(self, *args):
         print 
 
-    def on_cell_edited(self, *args):
-        print args
+    def on_cell_edited(self, renderer, path, value):
+        self.balls[int(path)].name = value
+        self.load_balls_to_treeview()
 
     def new_project(self, button):
         proj = NewProject(self.window)
+        project = proj.get_project()
+        proj.destroy()
 
         # This '1' was defined in the glade file
-        if proj.dialog.run() == 1:
-            self.load_project(proj.get_project())
-        proj.destroy()
+        if project:
+            self.load_project(project)
 
     def open_project(self, *args):
         fc = gtk.FileChooserDialog(_('Choose a gzv project'), self.window,
@@ -189,17 +199,51 @@ class Gzv(GladeLoader):
             self.load_project(Project.parse_file(proj_file))
         fc.destroy()
 
+    def save_project(self, *args):
+        fc = gtk.FileChooserDialog(_('Save project'), self.window,
+                                   action=gtk.FILE_CHOOSER_ACTION_SAVE,
+                                   buttons=(gtk.STOCK_CANCEL,
+                                            gtk.RESPONSE_CANCEL,
+                                            gtk.STOCK_SAVE,
+                                            gtk.RESPONSE_OK))
+        if fc.run() == gtk.RESPONSE_OK:
+            self.project.save_to_file(fc.get_filename())
+            self.balls.save_to_file(self.project.focus_points_file)
+        fc.destroy()
+
+
     def load_project(self, project):
         self.project = project
         self.balls = self.load_balls_from_file(project.focus_points_file)
         self.image = project.image
+
+        # loading the picture image and getting some useful
+        # information to draw it in the widget's background
+        try:
+            self.draw.set_from_file(project.image)
+        except gobject.GError:
+            msg = _("Couldn't recognize the image file format.")
+            dialog = gtk.MessageDialog(self.window,
+                                       gtk.DIALOG_MODAL,
+                                       gtk.MESSAGE_ERROR,
+                                       gtk.BUTTONS_CLOSE)
+            dialog.set_markup(msg)
+            dialog.run()
+            dialog.destroy()
+            return self.unload_project()
+
         self.load_balls_to_treeview()
+
+    def unload_project(self):
+        self.project = None
+        self.image = None
+        self.balls = BallManager()
         self.draw.queue_draw()
 
     def load_balls_to_treeview(self):
-        model = self.treeview.get_model()
+        self.model.clear()
         for i in self.balls:
-            model.append([i.position, i.name])
+            self.model.append([i.position, i.name])
 
     def load_balls_from_file(self, fname):
         balls = BallManager()
@@ -209,9 +253,9 @@ class Gzv(GladeLoader):
         for index, line in enumerate(file(fname)):
             if not line:
                 continue
-            pos, radios, name = line.split()
+            pos, radius, name = line.split(None, 2)
             x, y = pos.split(',')
-            balls.append(Ball(int(x), int(y), int(radios), name, index))
+            balls.append(Ball(x, y, radius, name.strip(), index))
         return balls
 
     def remove_fp(self, *args):
@@ -223,6 +267,7 @@ class Gzv(GladeLoader):
                 if i.position == int(position):
                     self.balls.remove(i)
             del model[path]
+            self.draw.queue_draw()
 
     def save_fp_list(self, *args):
         assert self.project is not None
@@ -249,48 +294,22 @@ class Gzv(GladeLoader):
         if not self.image:
             return
 
-        # loading the picture image and getting some useful
-        # information to draw it in the widget's background
-        img = gtk.gdk.pixbuf_new_from_file(self.image)
-        pixels = img.get_pixels()
-        rowstride = img.get_rowstride()
-        width = img.get_width()
-        height = img.get_height()
-        gc = draw.style.black_gc
-
-        # sets the correct size of the eventbox, to show the scrollbar
-        # when needed.
-        self.evtbox.set_size_request(width, height)
-
-        # drawing the picture in the background of the drawing area,
-        # this is really important.
-        draw.window.draw_rgb_image(gc, 0, 0, width, height,
-                                   'normal', pixels, rowstride,
-                                   0, 0)
-
-        # this call makes the ball being drown be shown correctly.
         self.draw_current_ball()
-
-        # drawing other balls stored in the self.balls list.
-        ctx = draw.window.cairo_create()
-        ctx.fill()
-
-        ctx.set_line_width(10.0)
-        ctx.set_source_rgba (0.5, 0.0, 0.0, 0.4)
-
         for i in self.balls:
-            ctx.arc(i.x, i.y, i.radios, 0, 64*math.pi)
+            self.draw_ball(i)
+        return False
 
+    def draw_ball(self, ball):
+        ctx = self.draw.window.cairo_create()
+        ctx.arc(ball.x, ball.y, ball.radius, 0, 64*math.pi)
+        ctx.set_source_rgba(0.5, 0.0, 0.0, 0.4)
         ctx.fill()
-        ctx.stroke()
 
     def draw_current_ball(self):
         if self.start_x < 0:
             return
-        ctx = self.draw.window.cairo_create()
-        ctx.arc(self.start_x, self.start_y, self.ball_width, 0, 64*math.pi)
-        ctx.set_source_rgba (0.5, 0.0, 0.0, 0.4)
-        ctx.fill()
+        ball = Ball(self.start_x, self.start_y, self.radius)
+        self.draw_ball(ball)
 
     def button_press(self, widget, event):
         if event.button == 1:
@@ -308,15 +327,21 @@ class Gzv(GladeLoader):
         self.draw.queue_draw()
 
         if event.x > self.last_x:
-            self.ball_width += 3
+            self.radius += 3
         else:
-            self.ball_width -= 3
+            self.radius -= 3
 
         self.last_x = event.x
 
     def finish_drawing(self):
-        self.draw_current_ball()
-        self.ball_width = Ball.DEFAULT_WIDTH
+        position = len(self.balls)
+        ball = Ball(self.start_x, self.start_y, self.radius, '', position)
+        self.balls.append(ball)
+        self.model.append([position, ''])
+        self.treeview.set_cursor(str(position), self.fpcolumn, True)
+
+        # returning to the standard radius
+        self.radius = Ball.DEFAULT_WIDTH
 
 if __name__ == '__main__':
     Gzv().window.show_all()