[go: up one dir, main page]

Menu

Diff of /src/main.py [000000] .. [r1]  Maximize  Restore

Switch to side-by-side view

--- a
+++ b/src/main.py
@@ -0,0 +1,267 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+#       main.py
+#       
+#       Copyright 2009-2010 Sandro Mani <manisandro@gmail.com>
+#       
+#       This program is free software; you can redistribute it and/or modify
+#       it under the terms of the GNU General Public License as published by
+#       the Free Software Foundation; either version 3 of the License, or
+#       (at your option) any later version.
+#       
+#       This program 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 General Public License
+#       along with this program; if not, write to the Free Software
+#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+#       MA 02110-1301, USA.
+
+
+import gtk
+import gtkspell
+import os
+import subprocess
+import tempfile
+
+import config
+import dialogs
+import drawingarea
+#import recognize
+
+class gimagereader:
+	def __init__(self,builder,filename=None):
+		self.window = builder.get_object("main")
+		if not self.window:
+			return
+		self.window.connect("destroy", gtk.main_quit)
+		# Some variables
+		self.builder=builder
+		self.status=builder.get_object("status_msg")
+		self.output=builder.get_object("output")
+		
+		self.curdir=None
+		self.filename=None
+		self.lang_count=0
+		self.lang=None
+		self.spellchecker=None
+		self.append_mode=0
+		
+		# Complete the GUI with some widgets
+		self.outbuffer=gtk.TextBuffer(None)
+		self.output.set_buffer(self.outbuffer)
+		
+		self.langcombo = gtk.combo_box_new_text()
+		builder.get_object("tb_language").add(self.langcombo)
+		self.langcombo.show()
+		self.langcombo.set_sensitive(False)
+		self.langcombo.connect('changed', self.set_language)
+		
+		self.appendcombo = gtk.combo_box_new_text()
+		builder.get_object("tb_appendmode").add(self.appendcombo)
+		self.appendcombo.append_text("At cursor")
+		self.appendcombo.append_text("At end")
+		self.appendcombo.append_text("Replace")
+		self.appendcombo.set_active(0)
+		self.appendcombo.show()
+		self.appendcombo.connect("changed", self.set_append)
+		self.drawingarea=drawingarea.drawingarea(builder)
+		
+		# Connect signals
+		dic = { "on_tb_openimg_clicked" : self.open_image,
+				"on_tb_zoomin_clicked" : (self.drawingarea.zoom,+0.1),
+				"on_tb_zoomout_clicked" : (self.drawingarea.zoom,-0.1),
+				"on_tb_bestzoom_clicked" : self.drawingarea.zoom_fit,
+				"on_tb_resetzoom_clicked" : self.drawingarea.zoom_reset,
+				"on_tb_lrotate_clicked" : (self.drawingarea.rotate,+90),
+				"on_tb_rrotate_clicked" : (self.drawingarea.rotate,-90),
+				"on_tb_doocr_clicked" : self.doocr,
+				"on_menu_open_activate" : self.open_image,
+				"on_menu_config_activate" : self.show_config,
+				"on_menu_zoomin_activate" : (self.drawingarea.zoom,+0.1),
+				"on_menu_zoomout_activate" : (self.drawingarea.zoom,-0.1),
+				"on_menu_bestzoom_activate" : self.drawingarea.zoom_fit,
+				"on_menu_resetzoom_activate" : self.drawingarea.zoom_reset,
+				"on_menu_lrotate_activate" : (self.drawingarea.rotate,+90),
+				"on_menu_rrotate_activate" : (self.drawingarea.rotate,-90),
+				"on_menu_about_activate" : self.about,
+				"on_btn_save_clicked": self.out_save,
+				"on_tb_clearout_clicked" : self.clearoutput,
+				"output_sel_change" : self.outputselchange,
+				"on_btn_stripcrlf_clicked" : self.stripcrlf,
+				"gtk_main_quit" : gtk.main_quit }
+		builder.connect_signals(dic)
+		
+		# Load other modules
+		self.window.show()
+		self.conf=config.config(builder)
+		if not self.conf.valid:
+			self.window.connect('event-after', gtk.main_quit)
+		else:
+			self.load_dictionaries()
+			if filename==None:
+				self.status.set_text("Open an image to begin...")
+				self.curdir=os.path.expanduser("~")
+			else:
+				self.load_image(filename)
+	
+	### Open and load images ###
+	def open_image(self,widget):
+		filename=dialogs.open_image(self.curdir,self.window)
+		if filename!="":
+			self.load_image(filename)
+	
+	def load_image(self,filename):
+		self.status.set_text("Loading '"+filename+"'...")
+		if not self.drawingarea.load(filename):
+			dialogs.error_dialog('Failed to load image','The file might not be an image or be corrupted.',self.window)
+			if self.filename==None:
+				self.status.set_text("Open an image to begin...")
+			else:
+				self.status.set_text("Drag a rectangle around the area to recognize, then press 'Recognize'...")
+			return
+		self.filename=filename
+		self.curdir=os.path.dirname(self.filename)
+		self.window.set_title(os.path.basename(self.filename)+" - gImageReader")
+		for obj in ("tb_zoomin", "tb_zoomout", "tb_bestzoom", "tb_resetzoom", "tb_rrotate", "tb_lrotate",
+					"menu_zoomin", "menu_zoomout", "menu_bestzoom", "menu_resetzoom", "menu_rrotate", "menu_lrotate"):
+			self.builder.get_object(obj).set_sensitive(True)
+		self.langcombo.set_sensitive(True)
+		self.clearoutput()
+		self.status.set_text("Drag a rectangle around the area to recognize, then press 'Recognize'...")
+	
+	### Recognition ###
+	def set_append(self,widget):
+		i = widget.get_active()
+		if i==-1:
+			return
+		self.append_mode=i
+	
+	def doocr(self,widget):
+		self.window.set_sensitive(False)
+		self.status.set_text('Recognizing area, please wait...')
+		if file==None or os.path.isfile(self.filename)==False:
+			dialogs.error_dialog('Failed to perform recognition',"The source file '"+self.filename+"' could not be found.",self.window)
+			self.window.set_sensitive(True)
+			self.status.set_text("Drag a rectangle around the area to recognize, then press 'Recognize'...")
+			return
+		# Create cropped file
+		sel=self.drawingarea.osel
+		temptif=tempfile.mkstemp('.tif','tmpocr')[1];
+		if sel[2]<0:
+			sel[0]+=sel[2]
+			sel[2]*=-1
+		if sel[3]<0:
+			sel[1]+=sel[3]
+			sel[3]*=-1
+		crop=str(int(sel[2]))+"x"+str(int(sel[3]))+"+"+str(int(sel[0]))+"+"+str(int(sel[1]))
+		p=subprocess.Popen([self.conf.conv_path+"convert",self.filename,"-depth","8","-compress","none","-rotate",str(self.drawingarea.angle),"-crop",crop,temptif], shell=False, stderr=subprocess.PIPE)
+		out=p.communicate()
+		if p.returncode!=0 or out[1]!='':
+			dialogs.error_dialog('Failed to perform recognition',"convert returned:\n"+out[1],self.window)
+			self.window.set_sensitive(True)
+			self.status.set_text("Drag a rectangle around the area to recognize, then press 'Recognize'...")
+			return
+		# Recognize
+		tmptxt=tempfile.mkstemp('.txt','tmpocr')[1];
+		p=subprocess.Popen([self.conf.tess_path+"tesseract",temptif,tmptxt[:-4],"-l",self.lang], shell=False, stderr=subprocess.PIPE)
+		out=p.communicate()
+		os.remove(temptif)
+		if p.returncode!=0 or (out[1]!='' and out[1]!="Tesseract Open Source OCR Engine\n"):
+			dialogs.error_dialog('Failed to perform recognition',"tesseract returned:\n"+out[1]+"\nThis probabily is a bug in tesseract, retry using an image at a different resolution or by varying the selected region.",self.window)
+			self.window.set_sensitive(True)
+			self.status.set_text("Drag a rectangle around the area to recognize, then press 'Recognize'...")
+			return
+		outfile = open(tmptxt, "r")
+		if self.append_mode==0: #at cursor (selection)
+			iters=self.outbuffer.get_selection_bounds()
+			if len(iters)!=0:
+				self.outbuffer.delete(iters[0],iters[1])			
+			self.outbuffer.insert_at_cursor(outfile.read())
+		elif self.append_mode==1: #at end
+			self.outbuffer.insert(self.outbuffer.get_end_iter(),outfile.read())
+		elif self.append_mode==2: #replace
+			self.outbuffer.set_text(outfile.read())
+		outfile.close()
+		os.remove(tmptxt)
+		if self.spellchecker!=None:
+			self.spellchecker.recheck_all()
+		self.builder.get_object("outputbox").show()
+		self.builder.get_object("hpane").set_position(-1)
+		self.status.set_text("Drag a rectangle around the area to recognize, then press 'Recognize'...")
+		self.window.set_sensitive(True)
+	
+	def outputselchange(self,widget,event):
+		self.builder.get_object("btn_stripcrlf").set_sensitive(self.outbuffer.get_has_selection()==True)
+	
+	def stripcrlf(self,widget):
+		self.output.set_editable(False)
+		iters=self.outbuffer.get_selection_bounds()
+		if len(iters)==0:
+			return #should not happen
+		txt=self.outbuffer.get_text(iters[0],iters[1])
+		txt=txt.replace("\n"," ").replace("  "," ")
+		self.outbuffer.delete(iters[0],iters[1])
+		self.outbuffer.insert_at_cursor(txt)
+		self.output.set_editable(True)
+		self.builder.get_object("btn_stripcrlf").set_sensitive(False)
+	
+	def out_save(self,widget):
+		savefile=dialogs.save_text(self.curdir)
+		if savefile=="":
+			return
+		try:
+			outfile = open(savefile, 'w')
+			outfile.write(self.outbuffer.get_text(self.outbuffer.get_start_iter(),self.outbuffer.get_end_iter()))
+			outfile.close()
+		except:
+			dialogs.error_dialog("Failed to save output","Check that you have writing permissions in the selected folder.",self.window)
+	
+	def clearoutput(self,widget=None):
+		self.outbuffer.set_text("")
+		self.builder.get_object("outputbox").hide()
+		
+	### Set and detect languages ###
+	def show_config(self,widget):
+		self.conf.show()
+		self.load_dictionaries()
+	
+	def load_dictionaries(self):
+		for i in range(0,self.lang_count):
+			self.langcombo.remove_text(0)
+		self.lang_count=0
+		for lang in (("eng","English"),("fra","French"),("deu","German"),("ita","Italian"),("spa","Spanish"),("nld","Dutch")):
+			if os.path.isfile(self.conf.dict_path+lang[0]+".unicharset"):
+				self.lang_count+=1
+				self.langcombo.append_text(lang[1])
+		if self.lang_count==0:
+			if dialogs.question_dialog("No dictionaries found","Do you want to correct the configuration? (Pressing 'No' will quit the program.)",self.window):
+				self.conf.show()
+			else:
+				self.window.connect('event-after', gtk.main_quit)
+		else:
+			self.langcombo.set_active(0)
+	
+	def set_language(self,widget):
+		list=widget.get_model()
+		i=widget.get_active()
+		if i==-1:
+			return
+		for lang in (("eng","English","en_US"),("fra","French","fr_FR"),("deu","German","de_DE"),("ita","Italian","it_IT"),("spa","Spanish","es_ES"),("nld","Dutch","nl_NL")):
+			if list[i][0]==lang[1]:
+				self.lang=lang[0]
+				if self.spellchecker!=None:
+					gtkspell.Spell.detach(self.spellchecker)
+					self.spellchecker=None
+				try:
+					self.spellchecker=gtkspell.Spell(self.output,lang[2])
+				except:
+					pass
+	### About ###
+	def about(self,widget):
+		response = self.builder.get_object("aboutdialog").run()
+		self.builder.get_object("aboutdialog").hide()
+