home *** CD-ROM | disk | FTP | other *** search
/ Freelog 116 / FreelogNo116-JuilletSeptembre2013.iso / Bureautique / gImageReader / gimagereader_0.9-1_win32.exe / bin / gimagereader / drawingarea.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2011-03-24  |  29KB  |  754 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.7)
  3.  
  4. import math
  5. import cairo
  6. import poppler
  7. import Image
  8. import ImageFilter
  9. import ImageEnhance
  10. import array
  11. import gtk
  12. import gobject
  13. import os
  14. import re
  15. import urllib
  16. import gettext
  17. import threadtools
  18. _ = gettext.gettext
  19.  
  20. class dotdict(dict):
  21.     ''' A dict class which allows member access by dot syntax. '''
  22.     
  23.     def __getattr__(self, attr):
  24.         return self.get(attr, None)
  25.  
  26.     __setattr__ = dict.__setitem__
  27.     __delattr__ = dict.__delitem__
  28.  
  29.  
  30. class Drawingarea:
  31.     ''' This class is responsible for the drawingarea section of the program. '''
  32.     
  33.     def __init__(self, builder, main):
  34.         ''' Constructor. '''
  35.         self.main = main
  36.         self.tb_bestzoom = builder.get_object('tb_bestzoom')
  37.         self.tb_resetzoom = builder.get_object('tb_resetzoom')
  38.         self.tb_zoomin = builder.get_object('tb_zoomin')
  39.         self.tb_zoomout = builder.get_object('tb_zoomout')
  40.         self.tb_toggle_controls = builder.get_object('tb_toggle_controls')
  41.         self.tb_doocr = builder.get_object('tb_doocr')
  42.         self.menu_doocr = gtk.Menu()
  43.         self.menu_doocr_current = gtk.MenuItem(_('Current Page'))
  44.         self.menu_doocr.append(self.menu_doocr_current)
  45.         self.menu_doocr_all = gtk.MenuItem(_('All Pages'))
  46.         self.menu_doocr.append(self.menu_doocr_all)
  47.         self.menu_doocr_pages = gtk.MenuItem(_('Pages...'))
  48.         self.menu_doocr.append(self.menu_doocr_pages)
  49.         self.menu_doocr.show_all()
  50.         self.dialog_pages = builder.get_object('dialog_pages')
  51.         self.entry_pages = builder.get_object('entry_pages')
  52.         self.menu_bestzoom = builder.get_object('menu_bestzoom')
  53.         self.menu_resetzoom = builder.get_object('menu_resetzoom')
  54.         self.menu_zoomin = builder.get_object('menu_zoomin')
  55.         self.menu_zoomout = builder.get_object('menu_zoomout')
  56.         self.menu_toggle_controls = builder.get_object('menu_toggle_controls')
  57.         self.layout = builder.get_object('layout')
  58.         self.scrolledwindow = builder.get_object('scrolledwindow')
  59.         self.hscrollbar = self.scrolledwindow.get_hscrollbar()
  60.         self.vscrollbar = self.scrolledwindow.get_vscrollbar()
  61.         self.hadjustment = self.scrolledwindow.get_hadjustment()
  62.         self.vadjustment = self.scrolledwindow.get_vadjustment()
  63.         self.toolbar_navigation = builder.get_object('toolbar_navigation')
  64.         self.spin_navigation_page = builder.get_object('spinbutton_navigation_page')
  65.         self.label_navigation_totpages = builder.get_object('label_navigation_totpages')
  66.         self.toolbar_controls = builder.get_object('toolbar_controls')
  67.         self.label_controls_dpi = builder.get_object('label_controls_dpi')
  68.         self.spin_controls_resolution = builder.get_object('spinbutton_controls_resolution')
  69.         self.spin_controls_resolution.set_value(200)
  70.         self.spin_controls_brightness = builder.get_object('spinbutton_controls_brightness')
  71.         self.spin_controls_contrast = builder.get_object('spinbutton_controls_contrast')
  72.         self.canvas_geo = dotdict({
  73.             'x': 0,
  74.             'y': 0,
  75.             'w': 0,
  76.             'h': 0,
  77.             'ow': 0,
  78.             'oh': 0,
  79.             'cw': 0,
  80.             'ch': 0,
  81.             's': 1,
  82.             'a': 0 })
  83.         self.canvas = gtk.DrawingArea()
  84.         self.canvas.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0.5, 0.5, 0.5))
  85.         self.canvas.set_size_request(self.canvas_geo.w, self.canvas_geo.h)
  86.         self.canvas.set_redraw_on_allocate(False)
  87.         self.layout.put(self.canvas, self.canvas_geo.x, self.canvas_geo.y)
  88.         self.zoom_fit = False
  89.         self.blur_timer = -1
  90.         self.controls_timer = -1
  91.         self.image = None
  92.         self.document = None
  93.         self.PILimage = None
  94.         self.selection = None
  95.         self.wsel = None
  96.         self.ssel = None
  97.         self.nsel = None
  98.         self.selcolor = [
  99.             0,
  100.             0,
  101.             1]
  102.         self._Drawingarea__selection_set_color()
  103.         self.scroll_animation = False
  104.         self.layout_scrollx = 0
  105.         self.layout_scrolly = 0
  106.         self.layout_width = 0
  107.         self.layout_height = 0
  108.         self.layout.add_events(gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK)
  109.         self.layout.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0.5, 0.5, 0.5))
  110.         self.scrolledwindow.connect('size_allocate', self._Drawingarea__scrolledwindow_resized)
  111.         self.layout.connect('scroll-event', self._Drawingarea__layout_scrolled)
  112.         self.canvas.connect('expose-event', self._Drawingarea__canvas_exposed)
  113.         self.canvas.connect('style_set', self._Drawingarea__selection_set_color)
  114.         self.layout.connect('button_press_event', self._Drawingarea__selection_start)
  115.         builder.get_object('tb_zoomin').connect('clicked', self.set_zoom, '+')
  116.         builder.get_object('tb_zoomout').connect('clicked', self.set_zoom, '-')
  117.         builder.get_object('tb_bestzoom').connect('clicked', self.set_zoom, 'f')
  118.         builder.get_object('tb_resetzoom').connect('clicked', self.set_zoom, 1)
  119.         builder.get_object('tb_lrotate').connect('clicked', self.rotate, +90)
  120.         builder.get_object('tb_rrotate').connect('clicked', self.rotate, -90)
  121.         self.tb_doocr.connect('clicked', self._Drawingarea__recognize)
  122.         self.menu_doocr_current.connect(('activate',), (lambda w: self.main.recognize()))
  123.         self.menu_doocr_all.connect('activate', self._Drawingarea__recognize_all)
  124.         self.menu_doocr_pages.connect('activate', self._Drawingarea__recognize_pages)
  125.         builder.get_object('menu_zoomin').connect('activate', self.set_zoom, '+')
  126.         builder.get_object('menu_zoomout').connect('activate', self.set_zoom, '-')
  127.         builder.get_object('menu_bestzoom').connect('activate', self.set_zoom, 'f')
  128.         builder.get_object('menu_resetzoom').connect('activate', self.set_zoom, 1)
  129.         builder.get_object('menu_lrotate').connect('activate', self.rotate, +90)
  130.         builder.get_object('menu_rrotate').connect('activate', self.rotate, -90)
  131.         self.menu_toggle_controls.connect('toggled', self._Drawingarea__toggle_controls)
  132.         self.tb_toggle_controls.connect('toggled', self._Drawingarea__toggle_controls)
  133.         self.spin_navigation_page.connect(('value-changed',), (lambda w: self._Drawingarea__render_page(w.get_value_as_int())))
  134.         self.spin_controls_resolution.connect('value-changed', self._Drawingarea__resolution_changed)
  135.         self.spin_controls_brightness.connect('value-changed', self._Drawingarea__brightness_contrast_changed)
  136.         self.spin_controls_contrast.connect('value-changed', self._Drawingarea__brightness_contrast_changed)
  137.         self.entry_pages.connect(('activate',), (lambda w: self.dialog_pages.response(gtk.RESPONSE_OK)))
  138.  
  139.     
  140.     def __scrolledwindow_resized(self, widget, event):
  141.         ''' Called when the scrolled window containing the canvas is resized. '''
  142.         if self.layout.allocation.width != self.layout_width or self.layout.allocation.height != self.layout_height:
  143.             self.layout_width = self.layout.allocation.width
  144.             self.layout_height = self.layout.allocation.height
  145.             if self.image == None:
  146.                 return None
  147.             if None.zoom_fit:
  148.                 self.set_zoom(None, 'f')
  149.             else:
  150.                 self._Drawingarea__position_canvas()
  151.  
  152.     
  153.     def __layout_scrolled(self, widget, event):
  154.         ''' Called when scroll events are captured on the layout widget. '''
  155.         if event.state & gtk.gdk.CONTROL_MASK == gtk.gdk.CONTROL_MASK:
  156.             if event.direction == gtk.gdk.SCROLL_UP and self.canvas_geo.s * 1.25 <= 10:
  157.                 self.set_zoom(None, '+', [
  158.                     float(event.x - self.canvas_geo.x) / self.canvas_geo.cw,
  159.                     float(event.y - self.canvas_geo.y) / self.canvas_geo.ch])
  160.             elif event.direction == gtk.gdk.SCROLL_DOWN and self.canvas_geo.s * 0.8 >= 0.1:
  161.                 self.set_zoom(None, '-', [
  162.                     float(event.x - self.canvas_geo.x) / self.canvas_geo.cw,
  163.                     float(event.y - self.canvas_geo.y) / self.canvas_geo.ch])
  164.             return True
  165.         return None
  166.  
  167.     
  168.     def __canvas_exposed(self, widget, event):
  169.         ''' Called when the canvas is to be repainted. '''
  170.         gobject.source_remove(self.blur_timer)
  171.         self.layout_scrollx = self.hadjustment.get_value()
  172.         self.layout_scrolly = self.vadjustment.get_value()
  173.         if self.image != None:
  174.             context = self.canvas.window.cairo_create()
  175.             context.save()
  176.             context.rectangle(event.area)
  177.             context.translate(self.canvas_geo.cw / 2, self.canvas_geo.ch / 2)
  178.             context.scale(self.canvas_geo.s, self.canvas_geo.s)
  179.             context.rotate((self.canvas_geo.a / 180) * 3.14159)
  180.             context.translate(-(self.canvas_geo.w) / 2, -(self.canvas_geo.h) / 2)
  181.             context.set_source_surface(self.image)
  182.             context.fill()
  183.             context.restore()
  184.             self._Drawingarea__selection_draw(context, event.area)
  185.             if self.canvas_geo.s < 1 and self.main.get_config().get_antialiasing():
  186.                 self.blur_timer = gobject.timeout_add(100, threadtools.SubprocessThread(self._Drawingarea__calc_downsampled, self._Drawingarea__draw_downsampled, event.area).start)
  187.             
  188.  
  189.     
  190.     def __calc_downsampled(self, area):
  191.         if self.image == None:
  192.             return [
  193.                 False]
  194.         w = None.image.get_width()
  195.         h = self.image.get_height()
  196.         image = Image.frombuffer('RGBA', (w, h), self.image.get_data(), 'raw', 'RGBA', 0, 1)
  197.         s = self.canvas_geo.s
  198.         w = int(round(w * s))
  199.         h = int(round(h * s))
  200.         image = image.resize((w, h), Image.ANTIALIAS)
  201.         surface = cairo.ImageSurface.create_for_data(array.array('B', image.tostring()), cairo.FORMAT_ARGB32, w, h, w * 4)
  202.         return [
  203.             True,
  204.             area,
  205.             surface,
  206.             w,
  207.             h,
  208.             s]
  209.  
  210.     
  211.     def __draw_downsampled(self, res):
  212.         if res[0] == True and res[5] == self.canvas_geo.s:
  213.             context = self.canvas.window.cairo_create()
  214.             context.save()
  215.             context.rectangle(res[1])
  216.             context.translate(self.canvas_geo.cw / 2, self.canvas_geo.ch / 2)
  217.             context.rotate((self.canvas_geo.a / 180) * 3.14159)
  218.             context.translate(-res[3] / 2, -res[4] / 2)
  219.             context.set_source_surface(res[2])
  220.             context.fill()
  221.             context.restore()
  222.             self._Drawingarea__selection_draw(context, res[1])
  223.  
  224.     
  225.     def __position_canvas(self, adjustments = None):
  226.         ''' Positions the canvas in order to center the image in the available area. '''
  227.         if not self.canvas.window:
  228.             return None
  229.         if None.canvas_geo.cw <= self.layout_width:
  230.             self.canvas_geo.x = int(round((self.layout_width - self.canvas_geo.cw) / 2))
  231.             lw = self.layout_width
  232.         else:
  233.             self.canvas_geo.x = 0
  234.             lw = self.canvas_geo.cw
  235.         if self.canvas_geo.ch <= self.layout_height:
  236.             self.canvas_geo.y = int(round((self.layout_height - self.canvas_geo.ch) / 2))
  237.             lh = self.layout_height
  238.         else:
  239.             self.canvas_geo.y = 0
  240.             lh = self.canvas_geo.ch
  241.         self.canvas.window.freeze_updates()
  242.         self.layout.set_size(lw, lh)
  243.         self.layout.move(self.canvas, self.canvas_geo.x, self.canvas_geo.y)
  244.         if adjustments != None:
  245.             self.hscrollbar.set_value(adjustments[0] * (self.hadjustment.get_upper() - self.hadjustment.get_page_size()))
  246.             self.vscrollbar.set_value(adjustments[1] * (self.vadjustment.get_upper() - self.vadjustment.get_page_size()))
  247.         self.canvas.window.thaw_updates()
  248.  
  249.     
  250.     def set_zoom(self, widget, mode, adjustments = None):
  251.         ''' Sets the zoom level. '''
  252.         self.zoom_fit = False
  253.         for widget in [
  254.             self.tb_bestzoom,
  255.             self.menu_bestzoom,
  256.             self.tb_resetzoom,
  257.             self.menu_resetzoom,
  258.             self.tb_zoomin,
  259.             self.menu_zoomin,
  260.             self.tb_zoomout,
  261.             self.menu_zoomout]:
  262.             widget.set_sensitive(True)
  263.         
  264.         if self.canvas_geo.a % 180 == 0:
  265.             best = min(float(self.layout_width) / self.canvas_geo.w, float(self.layout_height) / self.canvas_geo.h)
  266.         else:
  267.             best = min(float(self.layout_width) / self.canvas_geo.h, float(self.layout_height) / self.canvas_geo.w)
  268.         if type(mode) == str:
  269.             if mode == '+':
  270.                 self.canvas_geo.s *= 1.25
  271.                 if self.canvas_geo.s * 1.25 > 10:
  272.                     self.tb_zoomin.set_sensitive(False)
  273.                     self.menu_zoomin.set_sensitive(False)
  274.                 
  275.             elif mode == '-':
  276.                 self.canvas_geo.s *= 0.8
  277.                 if self.canvas_geo.s * 0.8 < 0.1:
  278.                     self.tb_zoomout.set_sensitive(False)
  279.                     self.menu_zoomout.set_sensitive(False)
  280.                 
  281.             if self.canvas_geo.s / best >= 0.9 or self.canvas_geo.s / best <= 1.09 or mode == 'f':
  282.                 self.zoom_fit = True
  283.                 self.tb_bestzoom.set_sensitive(False)
  284.                 self.menu_bestzoom.set_sensitive(False)
  285.                 self.canvas_geo.s = best
  286.             
  287.         elif type(mode) == int or type(mode) == float:
  288.             self.canvas_geo.s = float(mode)
  289.             if self.canvas_geo.s == 1:
  290.                 self.tb_resetzoom.set_sensitive(False)
  291.                 self.menu_resetzoom.set_sensitive(False)
  292.             
  293.         if adjustments == None:
  294.             adjustments = [
  295.                 xadj,
  296.                 yadj]
  297.         self.canvas_geo.cw = int(round(self.canvas_geo.w * self.canvas_geo.s))
  298.         self.canvas_geo.ch = int(round(self.canvas_geo.h * self.canvas_geo.s))
  299.         if self.ssel != None:
  300.             self.ssel[0] = int(round(self.nsel[0] * self.canvas_geo.s))
  301.             self.ssel[1] = int(round(self.nsel[1] * self.canvas_geo.s))
  302.             self.ssel[2] = int(round(self.nsel[2] * self.canvas_geo.s))
  303.             self.ssel[3] = int(round(self.nsel[3] * self.canvas_geo.s))
  304.         if self.canvas_geo.a % 180 != 0:
  305.             self.canvas_geo.cw = self.canvas_geo.ch
  306.             self.canvas_geo.ch = self.canvas_geo.cw
  307.         self.canvas.set_size_request(self.canvas_geo.cw, self.canvas_geo.ch)
  308.         self._Drawingarea__position_canvas(adjustments)
  309.  
  310.     
  311.     def rotate(self, widget, angle):
  312.         ''' Rotates the canvas. '''
  313.         self.canvas_geo.a = (360 + self.canvas_geo.a - angle) % 360
  314.         if self.ssel != None:
  315.             w = self.canvas_geo.w
  316.             h = self.canvas_geo.h
  317.             if self.canvas_geo.a % 180 == 0:
  318.                 w = h
  319.                 h = w
  320.             if angle == -90:
  321.                 self.ssel[0] = self.canvas_geo.ch - self.ssel[1] - self.ssel[3]
  322.                 self.ssel[1] = self.ssel[0]
  323.                 self.nsel[0] = h - self.nsel[1] - self.nsel[3]
  324.                 self.nsel[1] = self.nsel[0]
  325.             elif angle == 90:
  326.                 self.ssel[0] = self.ssel[1]
  327.                 self.ssel[1] = self.canvas_geo.cw - self.ssel[0] - self.ssel[2]
  328.                 self.nsel[0] = self.nsel[1]
  329.                 self.nsel[1] = w - self.nsel[0] - self.nsel[2]
  330.             self.ssel[2] = self.ssel[3]
  331.             self.ssel[3] = self.ssel[2]
  332.             self.nsel[2] = self.nsel[3]
  333.             self.nsel[3] = self.nsel[2]
  334.         if self.zoom_fit:
  335.             self.set_zoom(None, 'f')
  336.         else:
  337.             self.canvas_geo.cw = self.canvas_geo.ch
  338.             self.canvas_geo.ch = self.canvas_geo.cw
  339.             self.canvas.set_size_request(self.canvas_geo.cw, self.canvas_geo.ch)
  340.             self._Drawingarea__position_canvas()
  341.  
  342.     
  343.     def set_cursor(self, cursor):
  344.         ''' Sets the cursor over the drawingarea. '''
  345.         if cursor != None:
  346.             self.layout.window.set_cursor(cursor)
  347.         elif self.image != None:
  348.             self.layout.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.CROSSHAIR))
  349.         else:
  350.             self.layout.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
  351.  
  352.     
  353.     def __set_image_update_ui(self):
  354.         ''' Updates the UI after loading a new image (added through a gobject.idle_all
  355. \t\t\tto prevent a UI freeze since set_image is called in a different thread. '''
  356.         self.layout.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.CROSSHAIR))
  357.         self.canvas.show()
  358.         self.spin_controls_brightness.handler_block_by_func(self._Drawingarea__brightness_contrast_changed)
  359.         self.spin_controls_contrast.handler_block_by_func(self._Drawingarea__brightness_contrast_changed)
  360.         self.spin_controls_brightness.set_value(0)
  361.         self.spin_controls_contrast.set_value(0)
  362.         self.spin_controls_brightness.handler_unblock_by_func(self._Drawingarea__brightness_contrast_changed)
  363.         self.spin_controls_contrast.handler_unblock_by_func(self._Drawingarea__brightness_contrast_changed)
  364.         self.spin_controls_resolution.handler_block_by_func(self._Drawingarea__resolution_changed)
  365.         if self.document != None:
  366.             self.spin_controls_resolution.set_value(200)
  367.             self.label_navigation_totpages.set_text('/ %d' % self.document.get_n_pages())
  368.             self.spin_navigation_page.get_adjustment().set_upper(self.document.get_n_pages())
  369.             if self.spin_navigation_page.get_value_as_int() != 1:
  370.                 self.spin_navigation_page.set_value(1)
  371.             else:
  372.                 self._Drawingarea__render_page(1)
  373.             self.toolbar_navigation.show()
  374.             self.label_controls_dpi.set_text('dpi')
  375.         else:
  376.             self.spin_controls_resolution.set_value(100)
  377.             self.toolbar_navigation.hide()
  378.             self.label_controls_dpi.set_text('%')
  379.             self.set_zoom(None, 'f')
  380.         self.spin_controls_resolution.handler_unblock_by_func(self._Drawingarea__resolution_changed)
  381.         self.ssel = None
  382.         self.nsel = None
  383.         self.tb_doocr.set_label(_('Recognize all'))
  384.         self.tb_doocr.set_tooltip_text(_('Recognize entire image'))
  385.         return False
  386.  
  387.     
  388.     def set_image(self, filename):
  389.         ''' Loads an image or a PDF document. '''
  390.         if os.path.splitext(filename)[1].lower() == '.pdf':
  391.             
  392.             try:
  393.                 self.document = poppler.document_new_from_file('file:%s' % urllib.pathname2url(filename), None)
  394.             return False
  395.  
  396.         else:
  397.             
  398.             try:
  399.                 pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
  400.             except:
  401.                 return False
  402.  
  403.             self.document = None
  404.             self.image = cairo.ImageSurface(cairo.FORMAT_ARGB32, pixbuf.get_width(), pixbuf.get_height())
  405.             context = cairo.Context(self.image)
  406.             if pixbuf.get_has_alpha():
  407.                 context.set_source_rgba(1, 1, 1, 1)
  408.                 context.paint()
  409.             gdkcontext = gtk.gdk.CairoContext(context)
  410.             gdkcontext.set_source_pixbuf(pixbuf, 0, 0)
  411.             gdkcontext.paint()
  412.             self.PILimage = Image.frombuffer('RGBA', (self.image.get_width(), self.image.get_height()), self.image.get_data(), 'raw', 'RGBA', 0, 1).convert('RGB')
  413.             self.origPILimage = self.PILimage.copy()
  414.             self.canvas_geo.w = self.image.get_width()
  415.             self.canvas_geo.h = self.image.get_height()
  416.             self.canvas_geo.a = 0
  417.         gobject.idle_add(self._Drawingarea__set_image_update_ui)
  418.         return True
  419.  
  420.     
  421.     def __render_page(self, pageno):
  422.         ''' Renders the specified page on the canvas. '''
  423.         scale = self.spin_controls_resolution.get_value() / 72
  424.         page = self.document.get_page(pageno - 1)
  425.         (w, h) = page.get_size()
  426.         w = int(math.floor(w * scale))
  427.         h = int(math.floor(h * scale))
  428.         self.image = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
  429.         context = cairo.Context(self.image)
  430.         context.set_source_rgba(1, 1, 1, 1)
  431.         context.paint()
  432.         context.scale(scale, scale)
  433.         page.render(context)
  434.         self.PILimage = Image.frombuffer('RGBA', (self.image.get_width(), self.image.get_height()), self.image.get_data(), 'raw', 'RGBA', 0, 1).convert('RGB')
  435.         if self.nsel:
  436.             relscale = w / float(self.canvas_geo.w)
  437.             self.nsel = [ int(round(item * relscale)) for item in self.nsel ]
  438.         self.canvas_geo.w = w
  439.         self.canvas_geo.h = h
  440.         self.canvas_geo.a = 0
  441.         self._Drawingarea__set_brightness_contrast()
  442.         self.set_zoom(None, 'f')
  443.  
  444.     
  445.     def clear_image(self):
  446.         ''' Clears the displayed image. '''
  447.         if self.image != None:
  448.             self.image = None
  449.             self.canvas_geo = dotdict({
  450.                 'x': 0,
  451.                 'y': 0,
  452.                 'w': 0,
  453.                 'h': 0,
  454.                 'cw': 0,
  455.                 'ch': 0,
  456.                 's': 1,
  457.                 'a': 0 })
  458.             self.layout.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
  459.             self.ssel = None
  460.             self.nsel = None
  461.             self.canvas.hide()
  462.             self._Drawingarea__position_canvas()
  463.  
  464.     
  465.     def __selection_start(self, widget, event):
  466.         ''' Called when the user initiates selection with the mouse. '''
  467.         if self.image != None and self.wsel == None:
  468.             if self.ssel != None:
  469.                 area = gtk.gdk.Rectangle(self.ssel[0] - 1, self.ssel[1] - 1, self.ssel[2] + 2, self.ssel[3] + 2)
  470.                 self.ssel = None
  471.                 self._Drawingarea__canvas_exposed(None, dotdict({
  472.                     'area': area }))
  473.             self.wsel = [
  474.                 int(round(min(max(0, event.x - self.canvas_geo.x), self.canvas_geo.cw))),
  475.                 int(round(min(max(0, event.y - self.canvas_geo.y), self.canvas_geo.ch))),
  476.                 0,
  477.                 0]
  478.             self.ssel = [
  479.                 self.wsel[0],
  480.                 self.wsel[1],
  481.                 self.wsel[2],
  482.                 self.wsel[3]]
  483.             self.motionhandler = self.layout.connect('motion_notify_event', self._Drawingarea__select)
  484.             self.releasehandler = self.layout.connect('button_release_event', self._Drawingarea__selection_end)
  485.  
  486.     
  487.     def __scroll_by(self, dx, dy):
  488.         ''' Called when the user selects over the visible boundaries, initiating autoscrolling. '''
  489.         if not self.scroll_animation:
  490.             return False
  491.         oldW = None.wsel[2]
  492.         oldH = self.wsel[3]
  493.         self.wsel[2] += dx
  494.         self.wsel[3] += dy
  495.         self.ssel[0] = int(round(min(self.wsel[0], self.wsel[0] + self.wsel[2])))
  496.         self.ssel[1] = int(round(min(self.wsel[1], self.wsel[1] + self.wsel[3])))
  497.         self.ssel[2] = int(round(abs(self.wsel[2])))
  498.         self.ssel[3] = int(round(abs(self.wsel[3])))
  499.         x = int(round(self.wsel[0] + min(oldW, self.wsel[2]))) - 2
  500.         w = int(round(abs(oldW - self.wsel[2]))) + 4
  501.         y = int(round(self.wsel[1] + min(oldH, self.wsel[3]))) - 2
  502.         h = int(round(abs(oldH - self.wsel[3]))) + 4
  503.         self.canvas.window.freeze_updates()
  504.         self.canvas.window.invalidate_rect(gtk.gdk.Rectangle(self.ssel[0] - 2, y, self.ssel[2] + 4, h), False)
  505.         self.canvas.window.invalidate_rect(gtk.gdk.Rectangle(x, self.ssel[1] - 2, w, self.ssel[3] + 4), False)
  506.         self.canvas.window.invalidate_rect(gtk.gdk.Rectangle(x, y, w, h), False)
  507.         self.hscrollbar.set_value(self.hadjustment.get_value() + dx)
  508.         self.vscrollbar.set_value(self.vadjustment.get_value() + dy)
  509.         self.canvas.window.thaw_updates()
  510.         if self.scroll_animation:
  511.             gobject.timeout_add(100, self._Drawingarea__scroll_by, dx, dy)
  512.         return False
  513.  
  514.     
  515.     def __select(self, widget, event):
  516.         ''' Called during mouse motion after a started selection. '''
  517.         xspeed = yspeed = 0
  518.         if event.x - self.layout_scrollx <= 0 and self.layout_scrollx != 0:
  519.             xspeed = event.x - self.layout_scrollx
  520.         elif event.x - self.layout_scrollx >= self.layout_width and self.layout_scrollx != self.hadjustment.get_upper() - self.hadjustment.get_page_size():
  521.             xspeed = event.x - self.layout_scrollx - self.layout_width
  522.         if event.y - self.layout_scrolly <= 0 and self.layout_scrolly != 0:
  523.             yspeed = event.y - self.layout_scrolly
  524.         elif event.y - self.layout_scrolly >= self.layout_height and self.layout_scrolly != self.vadjustment.get_upper() - self.vadjustment.get_page_size():
  525.             yspeed = event.y - self.layout_scrolly - self.layout_height
  526.         if xspeed == 0 and yspeed == 0:
  527.             self.scroll_animation = False
  528.         else:
  529.             self.scroll_animation = True
  530.             gobject.timeout_add(100, self._Drawingarea__scroll_by, xspeed / 10, yspeed / 10)
  531.         oldW = self.wsel[2]
  532.         oldH = self.wsel[3]
  533.         self.wsel[2] = min(max(0, event.x - self.canvas_geo.x), self.canvas_geo.cw) - self.wsel[0]
  534.         self.wsel[3] = min(max(0, event.y - self.canvas_geo.y), self.canvas_geo.ch) - self.wsel[1]
  535.         self.ssel[0] = int(round(min(self.wsel[0], self.wsel[0] + self.wsel[2])))
  536.         self.ssel[1] = int(round(min(self.wsel[1], self.wsel[1] + self.wsel[3])))
  537.         self.ssel[2] = int(round(abs(self.wsel[2])))
  538.         self.ssel[3] = int(round(abs(self.wsel[3])))
  539.         x = int(round(self.wsel[0] + min(oldW, self.wsel[2]))) - 1
  540.         w = int(round(abs(oldW - self.wsel[2]))) + 2
  541.         y = int(round(self.wsel[1] + min(oldH, self.wsel[3]))) - 1
  542.         h = int(round(abs(oldH - self.wsel[3]))) + 2
  543.         self.canvas.window.freeze_updates()
  544.         self._Drawingarea__canvas_exposed(None, dotdict({
  545.             'area': gtk.gdk.Rectangle(x, self.ssel[1] - 1, w, self.ssel[3] + 2) }))
  546.         self._Drawingarea__canvas_exposed(None, dotdict({
  547.             'area': gtk.gdk.Rectangle(self.ssel[0] - 1, y, self.ssel[2] + 2, h) }))
  548.         self._Drawingarea__canvas_exposed(None, dotdict({
  549.             'area': gtk.gdk.Rectangle(x, y, w, h) }))
  550.         self.canvas.window.thaw_updates()
  551.  
  552.     
  553.     def __selection_end(self, widget, event):
  554.         ''' Called when the user releases the mouse button to stop selecting. '''
  555.         self.layout.disconnect(self.motionhandler)
  556.         self.layout.disconnect(self.releasehandler)
  557.         self.scroll_animation = False
  558.         self.wsel = None
  559.         if self.ssel[2] == 0 or self.ssel[3] == 0:
  560.             self.tb_doocr.set_label(_('Recognize all'))
  561.             self.tb_doocr.set_tooltip_text(_('Recognize entire image'))
  562.             area = gtk.gdk.Rectangle(self.ssel[0] - 1, self.ssel[1] - 1, 2, 2)
  563.             self.nsel = None
  564.             self.ssel = None
  565.             self._Drawingarea__canvas_exposed(None, dotdict({
  566.                 'area': area }))
  567.         else:
  568.             self.tb_doocr.set_label(_('Recognize selection'))
  569.             self.tb_doocr.set_tooltip_text(_('Recognize selected region'))
  570.             self.nsel = [ int(round(value / self.canvas_geo.s)) for value in self.ssel ]
  571.  
  572.     
  573.     def __selection_draw(self, context, area):
  574.         if self.ssel != None:
  575.             context.push_group()
  576.             context.rectangle(self.ssel[0] + 0.5, self.ssel[1] + 0.5, self.ssel[2] - 1, self.ssel[3] - 1)
  577.             context.set_source_rgba(self.selcolor[0], self.selcolor[1], self.selcolor[2], 0.25)
  578.             context.fill()
  579.             context.set_line_width(1)
  580.             context.set_source_rgb(self.selcolor[0], self.selcolor[1], self.selcolor[2])
  581.             context.move_to(self.ssel[0] + 0.5, self.ssel[1] + 0.5)
  582.             context.rel_line_to(self.ssel[2] - 1, 0)
  583.             context.rel_line_to(0, self.ssel[3] - 1)
  584.             context.rel_line_to(-self.ssel[2] + 1, 0)
  585.             context.close_path()
  586.             context.stroke()
  587.             context.pop_group_to_source()
  588.             sel = gtk.gdk.Rectangle(self.ssel[0] - 1, self.ssel[1] - 1, self.ssel[2] + 2, self.ssel[3] + 2)
  589.             context.rectangle(area.intersect(sel))
  590.             context.fill()
  591.  
  592.     
  593.     def __selection_set_color(self, widget = None, event = None):
  594.         ''' Sets the selection color based on the GTK theme color scheme. '''
  595.         color = gtk.settings_get_default().get_properties('gtk-color-scheme')[0]
  596.         i = color.find('selected_bg_color: ')
  597.         if i == -1:
  598.             self.selcolor = [
  599.                 0,
  600.                 0,
  601.                 1]
  602.             return None
  603.         j = None[i:].find('\n')
  604.         
  605.         try:
  606.             color = gtk.gdk.color_parse(color[i + 19:i + j])
  607.             self.selcolor = [
  608.                 color.red / 65535,
  609.                 color.green / 65535,
  610.                 color.blue / 65535]
  611.         except:
  612.             self.selcolor = [
  613.                 0,
  614.                 0,
  615.                 1]
  616.  
  617.  
  618.     
  619.     def get_selection(self, page = None):
  620.         ''' Returns a PIL image object containing the selected part of the image of the specified page. If page is not specified, the current image is taken. '''
  621.         if page != None:
  622.             self.spin_navigation_page.set_value(page)
  623.         if self.nsel == None:
  624.             selection = Image.frombuffer('RGBA', (self.canvas_geo.w, self.canvas_geo.h), self.image.get_data(), 'raw', 'RGBA', 0, 1)
  625.             if self.canvas_geo.a != 0:
  626.                 selection = selection.rotate(-(self.canvas_geo.a))
  627.             
  628.         else:
  629.             rw = self.canvas_geo.w
  630.             rh = self.canvas_geo.h
  631.             if self.canvas_geo.a % 180 != 0:
  632.                 rw = rh
  633.                 rh = rw
  634.             surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.nsel[2], self.nsel[3])
  635.             context = cairo.Context(surf)
  636.             context.translate(-self.nsel[0] + rw / 2, -self.nsel[1] + rh / 2)
  637.             context.rotate((self.canvas_geo.a / 180) * 3.14159)
  638.             context.translate(-(self.canvas_geo.w) / 2, -(self.canvas_geo.h) / 2)
  639.             context.set_source_surface(self.image)
  640.             context.paint()
  641.             selection = Image.frombuffer('RGBA', (self.nsel[2], self.nsel[3]), surf.get_data(), 'raw', 'RGBA', 0, 1)
  642.         return selection.convert('RGB')
  643.  
  644.     
  645.     def __toggle_controls(self, widget):
  646.         active = widget.get_active()
  647.         if active:
  648.             self.toolbar_controls.show()
  649.         else:
  650.             self.toolbar_controls.hide()
  651.         self.menu_toggle_controls.handler_block_by_func(self._Drawingarea__toggle_controls)
  652.         self.tb_toggle_controls.handler_block_by_func(self._Drawingarea__toggle_controls)
  653.         self.menu_toggle_controls.set_active(active)
  654.         self.tb_toggle_controls.set_active(active)
  655.         self.menu_toggle_controls.handler_unblock_by_func(self._Drawingarea__toggle_controls)
  656.         self.tb_toggle_controls.handler_unblock_by_func(self._Drawingarea__toggle_controls)
  657.  
  658.     
  659.     def __brightness_contrast_changed(self, widget = None):
  660.         ''' Called when either the brightness or the contrast spin changes. '''
  661.         gobject.source_remove(self.controls_timer)
  662.         self.controls_timer = gobject.timeout_add(100, self._Drawingarea__set_brightness_contrast)
  663.  
  664.     
  665.     def __set_brightness_contrast(self):
  666.         ''' Changes the brightness and contrast of the image. '''
  667.         w = self.canvas_geo.w
  668.         h = self.canvas_geo.h
  669.         im = ImageEnhance.Brightness(self.PILimage).enhance(1 + self.spin_controls_brightness.get_value() / 100)
  670.         im = ImageEnhance.Contrast(im).enhance(1 + self.spin_controls_contrast.get_value() / 100)
  671.         im = im.convert('RGBA')
  672.         self.image = cairo.ImageSurface.create_for_data(array.array('B', im.tostring()), cairo.FORMAT_ARGB32, w, h, w * 4)
  673.         self.canvas.queue_draw()
  674.         self.controls_timer = -1
  675.         return False
  676.  
  677.     
  678.     def __resolution_changed(self, widget):
  679.         ''' Called when the resolution spinbutton is changed. '''
  680.         gobject.source_remove(self.controls_timer)
  681.         self.controls_timer = gobject.timeout_add(100, self._Drawingarea__change_resolution)
  682.  
  683.     
  684.     def __change_resolution(self):
  685.         ''' Changes the resolution of the image. '''
  686.         if self.document != None:
  687.             self._Drawingarea__render_page(self.spin_navigation_page.get_value_as_int())
  688.         else:
  689.             scale = self.spin_controls_resolution.get_value() / 100
  690.             newsize = [ int(round(dim * scale)) for dim in self.origPILimage.size ]
  691.             self.PILimage = self.origPILimage.resize(newsize, Image.ANTIALIAS)
  692.             if self.nsel:
  693.                 relscale = newsize[0] / float(self.canvas_geo.w)
  694.                 self.nsel = [ int(round(item * relscale)) for item in self.nsel ]
  695.             (self.canvas_geo.w, self.canvas_geo.h) = newsize
  696.             self._Drawingarea__set_brightness_contrast()
  697.             self.set_zoom(None, 'f')
  698.         self.controls_timer = -1
  699.         return False
  700.  
  701.     
  702.     def __recognize(self, widget):
  703.         if self.document != None and self.document.get_n_pages() > 1 and self.nsel == None:
  704.             self.menu_doocr.popup(None, None, self._Drawingarea__doocr_menu_positioner, 1, gtk.get_current_event_time())
  705.         else:
  706.             self.main.recognize()
  707.  
  708.     
  709.     def __doocr_menu_positioner(self, menu):
  710.         (x, y) = self.main.window.window.get_origin()
  711.         x += self.tb_doocr.allocation.x
  712.         y += self.tb_doocr.allocation.y
  713.         return (x, y, False)
  714.  
  715.     
  716.     def __recognize_all(self, widget):
  717.         self.main.recognize(range(1, self.document.get_n_pages() + 1))
  718.  
  719.     
  720.     def __recognize_pages(self, widget):
  721.         self.entry_pages.set_text('')
  722.         self.entry_pages.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.main.get_config().get_color('base_color')))
  723.         while True:
  724.             response = self.dialog_pages.run()
  725.             self.entry_pages.grab_focus()
  726.             if response == gtk.RESPONSE_OK:
  727.                 pages = []
  728.                 ranges = [ r.split('-') for r in re.sub('\\s+', '', self.entry_pages.get_text()).split(',') ]
  729.                 
  730.                 try:
  731.                     for r in ranges:
  732.                         if len(r) == 1:
  733.                             pages.append(int(r[0]))
  734.                             continue
  735.                         if len(r) == 2:
  736.                             pages += range(int(r[0]), int(r[1]) + 1)
  737.                             continue
  738.                         raise 
  739.                     
  740.                     pages = list(set(pages))
  741.                     pages.sort()
  742.                     N = self.document.get_n_pages()
  743.                     pages = (filter,)((lambda x: if x > 0:
  744. passx <= N), pages)
  745.                     if pages:
  746.                         self.main.recognize(pages)
  747.                 self.entry_pages.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse('#FF8080'))
  748.  
  749.                 continue
  750.             break
  751.         self.dialog_pages.hide()
  752.  
  753.  
  754.