Andrea Corbellini has proposed merging lp:~andrea-bs/a4/display-image into 
lp:a4.

Requested reviews:
  A4 development (a4-dev)


This branch is nothing special. It just adds some code to open and display SVG 
images. The UI is composed of three main widgets: the menu bar, the drawing 
area and the status bar. I haven't added a toolbar to reserve more space to the 
drawing area, we may add it later if it turns out to be useful.

This code is fully PEP-8 compliant and almost all the exceptional cases are 
threated correctly (see the TODOs).
-- 
https://code.launchpad.net/~andrea-bs/a4/display-image/+merge/26180
Your team A4 development is requested to review the proposed merge of 
lp:~andrea-bs/a4/display-image into lp:a4.
=== modified file 'a4'
--- a4	2010-05-21 14:30:23 +0000
+++ a4	2010-05-27 14:33:28 +0000
@@ -1,3 +1,8 @@
 #!/usr/bin/python
 # Copyright 2010 A4 Developers.  This software is licensed under the
 # GNU General Public License version 3 (see the file LICENSE).
+
+from a4lib.app import main
+
+if __name__ == '__main__':
+    main()

=== added file 'a4lib/app.py'
--- a4lib/app.py	1970-01-01 00:00:00 +0000
+++ a4lib/app.py	2010-05-27 14:33:28 +0000
@@ -0,0 +1,113 @@
+# Copyright 2010 A4 Developers.  This software is licensed under the
+# GNU General Public License version 3 (see the file LICENSE).
+
+"""The ingress point of the application."""
+
+import optparse
+import os
+import gtk
+from a4lib.svgimage import SVGImage, SVGImageError
+
+class WindowMain(object):
+    """The main window of the application."""
+
+    def __init__(self):
+        self.svg_image = None
+        self.builder = gtk.Builder()
+        # TODO Look into '/usr/share' too.
+        self.builder.add_from_file('ui/window_main.glade')
+        self.builder.connect_signals(self)
+
+        self.gtk_window = self.builder.get_object('window_main')
+        self.gtk_window.show_all()
+        self.drawing_area = self.builder.get_object('drawing_area').window
+
+    def set_status(self, status):
+        """Put the given string in the status bar."""
+        label = self.builder.get_object('label_status')
+        label.set_text(status)
+
+    def open_file(self, file_name):
+        """Open a file inside this window."""
+        self.set_status('Loading {0}...'.format(file_name))
+        try:
+            # Try to open a file.
+            image = SVGImage(file_name)
+        except SVGImageError as error:
+            # The file doesn't exist, or is not an SVG file. Show an error
+            # dialog and don't do anything else.
+            dialog = gtk.MessageDialog(
+                self.gtk_window, gtk.DIALOG_DESTROY_WITH_PARENT,
+                gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE,
+                'Cannot open {0!r}: {1[0]}'.format(file_name, error.args))
+            dialog.run()
+            dialog.destroy()
+        else:
+            # The file was OK. Set up the environment.
+            widget = self.builder.get_object('drawing_area')
+            widget.set_size_request(image.width + 20, image.height + 20)
+            self.svg_image = image
+        finally:
+            # Restore the status string.
+            self.set_status('')
+
+    def on_open_clicked(self, widget):
+        """Even called when the 'Open' button is clicked."""
+        # Set up the file chooser dialog.
+        dialog = gtk.FileChooserDialog(
+            None, None, gtk.FILE_CHOOSER_ACTION_OPEN, (
+                gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
+                gtk.STOCK_OPEN, gtk.RESPONSE_OK)
+            )
+        dialog.set_default_response(gtk.RESPONSE_OK)
+        # If an another file has been opened, use its location as starting
+        # folder for the dialog.
+        if self.svg_image is not None:
+            path = os.path.dirname(self.svg_image.file_name)
+            dialog.set_current_folder(path)
+
+        # Show the dialog, back up the relevant properties and destroy it.
+        response = dialog.run()
+        file_name = dialog.get_filename()
+        dialog.destroy()
+        # Open the file, if necessary.
+        if response == gtk.RESPONSE_OK:
+            self.open_file(file_name)
+
+    def on_drawing_area_expose(self, widget, event):
+        """This method is called everytime the drawing area should be redrawn.
+        """
+        image = self.svg_image
+        if image is None:
+            return
+        context = self.drawing_area.cairo_create()
+
+        context.rectangle(
+            event.area.x, event.area.y, event.area.width, event.area.height)
+        context.clip()
+        context.set_source_rgb(1, 1, 1)
+        context.paint()
+
+        width, height = self.drawing_area.get_size()
+        context.translate(
+            (width - image.width) / 2, (height - image.height) / 2)
+        image.render_cairo(context)
+
+    def quit(self, widget=None):
+        """Close the window and quit the application."""
+        gtk.main_quit()
+
+
+def parse_arguments(args=None):
+    """Parse the command line arguments."""
+    parser = optparse.OptionParser()
+    return parser.parse_args(args)
+
+def main(args=None):
+    """Start the application."""
+    options, files = parse_arguments(args)
+    window = WindowMain()
+    if files:
+        # TODO What if more than one file is given?
+        window.open_file(files[0])
+    gtk.main()

=== added file 'a4lib/svgimage.py'
--- a4lib/svgimage.py	1970-01-01 00:00:00 +0000
+++ a4lib/svgimage.py	2010-05-27 14:33:28 +0000
@@ -0,0 +1,28 @@
+# Copyright 2010 A4 Developers.  This software is licensed under the
+# GNU General Public License version 3 (see the file LICENSE).
+
+"""Code to deal with SVG images."""
+
+import rsvg
+from glib import GError
+
+
+class SVGImageError(StandardError):
+    """Error raised when an operation with an image fails."""
+
+
+class SVGImage(object):
+    """An object that represents an image contained in a SVG file."""
+
+    def __init__(self, file_name):
+        self.file_name = file_name
+        try:
+            svg_data = open(file_name).read()
+            self._svg_handler = rsvg.Handle(data=svg_data)
+        except IOError as error:
+            raise SVGImageError(error.args[1])
+        except GError as error:
+            raise SVGImageError('Unknown file type')
+        self.width = self._svg_handler.get_property('width')
+        self.height = self._svg_handler.get_property('height')
+        self.render_cairo = self._svg_handler.render_cairo

=== added directory 'ui'
=== added file 'ui/window_main.glade'
--- ui/window_main.glade	1970-01-01 00:00:00 +0000
+++ ui/window_main.glade	2010-05-27 14:33:28 +0000
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkWindow" id="window_main">
+    <property name="title" translatable="yes">A4</property>
+    <property name="icon_name">emblem-documents</property>
+    <signal name="destroy" handler="quit"/>
+    <child>
+      <object class="GtkVBox" id="vbox1">
+        <property name="visible">True</property>
+        <child>
+          <object class="GtkMenuBar" id="menubar1">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkMenuItem" id="menuitem_file">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_File</property>
+                <property name="use_underline">True</property>
+                <child type="submenu">
+                  <object class="GtkMenu" id="menu_file">
+                    <property name="visible">True</property>
+                    <child>
+                      <object class="GtkImageMenuItem" id="imagemenuitem_open">
+                        <property name="label">gtk-open</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                        <signal name="activate" handler="on_open_clicked"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkSeparatorMenuItem" id="separatormenuitem1">
+                        <property name="visible">True</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkImageMenuItem" id="imagemenuitem_quit">
+                        <property name="label">gtk-quit</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                        <signal name="activate" handler="quit"/>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkMenuItem" id="menuitem_help">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_Help</property>
+                <property name="use_underline">True</property>
+                <child type="submenu">
+                  <object class="GtkMenu" id="menu_help">
+                    <property name="visible">True</property>
+                    <child>
+                      <object class="GtkImageMenuItem" id="imagemenuitem_about">
+                        <property name="label">gtk-about</property>
+                        <property name="visible">True</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow1">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hscrollbar_policy">automatic</property>
+            <property name="vscrollbar_policy">automatic</property>
+            <child>
+              <object class="GtkViewport" id="viewport1">
+                <property name="visible">True</property>
+                <property name="resize_mode">queue</property>
+                <child>
+                  <object class="GtkDrawingArea" id="drawing_area">
+                    <property name="visible">True</property>
+                    <signal name="expose_event" handler="on_drawing_area_expose"/>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkStatusbar" id="statusbar1">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkLabel" id="label_status">
+                <property name="visible">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>

_______________________________________________
Mailing list: https://launchpad.net/~a4-dev
Post to     : a4-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~a4-dev
More help   : https://help.launchpad.net/ListHelp

Rispondere a