def openTemplate(self): if not Rpc.session.logged(): if not self.login(): return dialog = OpenTemplateDialog(self) if dialog.exec_() == QDialog.Rejected: return model = dialog.group[dialog.id] self._template = Template(model.value('name')) self._template.id = model.id fields = Rpc.session.execute('/object', 'execute', 'nan.template.box', 'fields_get') model.value('boxes').addFields(fields) for x in model.value('boxes'): box = TemplateBox() box.rect = QRectF(x.value('x'), x.value('y'), x.value('width'), x.value('height')) box.featureRect = QRectF(x.value('feature_x'), x.value('feature_y'), x.value('feature_width'), x.value('feature_height')) box.name = x.value('name') box.text = x.value('text') box.recognizer = x.value('recognizer') box.type = x.value('type') box.filter = x.value('filter') self._template.addBox(box) self.scene.setTemplate(self._template) self.updateTitle()
def loadAll(): fields = ['name', 'boxes'] templateFields = Rpc.session.execute('/object', 'execute', 'nan.template', 'fields_get', fields) fields = ['x', 'y', 'width', 'height', 'feature_x', 'feature_y', 'feature_width', 'feature_height', 'name', 'text', 'recognizer', 'type', 'filter' ] boxFields = Rpc.session.execute('/object', 'execute', 'nan.template.box', 'fields_get', fields) ids = Rpc.session.execute('/object', 'execute', 'nan.template', 'search', []) group = RecordGroup( 'nan.template', templateFields, ids ) templates = [] for record in group: template = Template( record.value('name') ) template.id = record.id record.value('boxes').addFields(boxFields) for boxRecord in record.value('boxes'): box = TemplateBox() box.rect = QRectF( boxRecord.value('x'), boxRecord.value('y'), boxRecord.value('width'), boxRecord.value('height') ) box.featureRect = QRectF( boxRecord.value('feature_x'), boxRecord.value('feature_y'), boxRecord.value('feature_width'), boxRecord.value('feature_height') ) box.name = boxRecord.value('name') box.text = boxRecord.value('text') box.recognizer = boxRecord.value('recognizer') box.type = boxRecord.value('type') box.filter = boxRecord.value('filter') template.addBox( box ) templates.append( template ) return templates
def newTemplate(self): answer = QMessageBox.question( self, _('New Template'), _('Do you want to save changes to the current template?'), QMessageBox.Save | QMessageBox.No | QMessageBox.Cancel) if answer == QMessageBox.Cancel: return elif answer == QMessageBox.Save: if not self.saveTemplate(): return self._template = Template(self.Unnamed) self.scene.setTemplate(self._template) self.updateTitle()
def openTemplate(self): if not Rpc.session.logged(): if not self.login(): return dialog = OpenTemplateDialog(self) if dialog.exec_() == QDialog.Rejected: return model = dialog.group[dialog.id] self._template = Template( model.value('name') ) self._template.id = model.id fields = Rpc.session.execute('/object', 'execute', 'nan.template.box', 'fields_get') model.value('boxes').addFields( fields ) for x in model.value('boxes'): box = TemplateBox() box.rect = QRectF( x.value('x'), x.value('y'), x.value('width'), x.value('height') ) box.featureRect = QRectF( x.value('feature_x'), x.value('feature_y'), x.value('feature_width'), x.value('feature_height') ) box.name = x.value('name') box.text = x.value('text') box.recognizer = x.value('recognizer') box.type = x.value('type') box.filter = x.value('filter') self._template.addBox( box ) self.scene.setTemplate(self._template) self.updateTitle()
def newTemplate(self): answer = QMessageBox.question(self, _('New Template'), _('Do you want to save changes to the current template?'), QMessageBox.Save | QMessageBox.No | QMessageBox.Cancel ) if answer == QMessageBox.Cancel: return elif answer == QMessageBox.Save: if not self.saveTemplate(): return self._template = Template( self.Unnamed ) self.scene.setTemplate( self._template ) self.updateTitle()
def getTemplateFromData(self, cr, uid, data): template = Template(data['name']) template.id = data['id'] ids = self.pool.get('nan.template.box').search( cr, uid, [('template', '=', data['id'])]) boxes = self.pool.get('nan.template.box').read(cr, uid, ids) for y in boxes: box = TemplateBox() box.id = y['id'] box.rect = QRectF(y['x'], y['y'], y['width'], y['height']) box.name = y['name'] box.text = y['text'] box.recognizer = y['recognizer'] box.type = y['type'] box.filter = y['filter'] # Important step: ensure box.text is unicode! if isinstance(box.text, str): box.text = unicode(box.text, 'latin-1') template.addBox(box) print "GETTING TEMPLATE: %s WITH %d BOXES" % (data['name'], len(boxes)) return template
def loadAll(): fields = ['name', 'boxes'] templateFields = Rpc.session.execute('/object', 'execute', 'nan.template', 'fields_get', fields) fields = [ 'x', 'y', 'width', 'height', 'feature_x', 'feature_y', 'feature_width', 'feature_height', 'name', 'text', 'recognizer', 'type', 'filter' ] boxFields = Rpc.session.execute('/object', 'execute', 'nan.template.box', 'fields_get', fields) ids = Rpc.session.execute('/object', 'execute', 'nan.template', 'search', []) group = RecordGroup('nan.template', templateFields, ids) templates = [] for record in group: template = Template(record.value('name')) template.id = record.id record.value('boxes').addFields(boxFields) for boxRecord in record.value('boxes'): box = TemplateBox() box.rect = QRectF(boxRecord.value('x'), boxRecord.value('y'), boxRecord.value('width'), boxRecord.value('height')) box.featureRect = QRectF(boxRecord.value('feature_x'), boxRecord.value('feature_y'), boxRecord.value('feature_width'), boxRecord.value('feature_height')) box.name = boxRecord.value('name') box.text = boxRecord.value('text') box.recognizer = boxRecord.value('recognizer') box.type = boxRecord.value('type') box.filter = boxRecord.value('filter') template.addBox(box) templates.append(template) return templates
def getTemplateFromData(self, cr, uid, data, context=None): template = Template( data['name'] ) template.id = data['id'] template.analysisFunction = data['analysis_function'] ids = self.pool.get('nan.template.box').search( cr, uid, [('template_id','=',data['id'])], context=context ) boxes = self.pool.get('nan.template.box').read(cr, uid, ids, context=context) for y in boxes: box = TemplateBox() box.id = y['id'] box.rect = QRectF( y['x'], y['y'], y['width'], y['height'] ) box.name = y['name'] box.text = y['text'] box.recognizer = y['recognizer'] box.type = y['type'] box.filter = y['filter'] # Important step: ensure box.text is unicode! if isinstance( box.text, str ): box.text = str( box.text, 'latin-1' ) template.addBox( box ) return template
def __init__(self, parent=None): QMainWindow.__init__(self, parent) loadUi('mainwindow.ui', self) self.scene = DocumentScene() self.uiView.setScene(self.scene) self.uiView.setRenderHints(QPainter.Antialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform) self.uiView.setCacheMode(QGraphicsView.CacheBackground) self._template = Template(self.Unnamed) self.scene.setTemplate(self._template) self.uiTool = ToolWidget(self.uiToolDock) self.undoGroup = QUndoGroup(self) stack = QUndoStack(self.undoGroup) self.undoGroup.setActiveStack(stack) # Let default Qt Undo and Redo Actions handle the Undo/Redo actions # And put them at the very beggining of the Edit menu undoAction = self.undoGroup.createUndoAction(self.menuEdit) undoAction.setShortcut("Ctrl+Z") redoAction = self.undoGroup.createRedoAction(self.menuEdit) redoAction.setShortcut("Ctrl+Shift+Z") if self.menuEdit.actions(): firstAction = self.menuEdit.actions()[0] else: firstAction = None self.menuEdit.insertAction(firstAction, undoAction) self.menuEdit.insertAction(firstAction, redoAction) self.connect(self.scene, SIGNAL('newTemplateBox(QRectF)'), self.newTemplateBox) self.connect( self.scene, SIGNAL('currentTemplateBoxChanged(PyQt_PyObject,PyQt_PyObject)'), self.currentTemplateBoxChanged) self.connect(self.scene, SIGNAL('mouseMoved'), self.sceneMouseMoved) self.connect(self.actionExit, SIGNAL('triggered()'), self.close) self.connect(self.actionOpenImage, SIGNAL('triggered()'), self.openImage) self.connect(self.actionOpenTemplate, SIGNAL('triggered()'), self.openTemplate) self.connect(self.actionToggleImageBoxes, SIGNAL('triggered()'), self.toggleImageBoxes) self.connect(self.actionToggleTemplateBoxes, SIGNAL('triggered()'), self.toggleTemplateBoxes) self.connect(self.actionToggleFeatureBoxes, SIGNAL('triggered()'), self.toggleFeatureBoxes) self.connect(self.actionToggleBinarized, SIGNAL('triggered()'), self.toggleBinarized) self.connect(self.actionLogin, SIGNAL('triggered()'), self.login) self.connect(self.actionSaveTemplate, SIGNAL('triggered()'), self.saveTemplate) self.connect(self.actionSaveTemplateAs, SIGNAL('triggered()'), self.saveTemplateAs) self.connect(self.actionNewTemplate, SIGNAL('triggered()'), self.newTemplate) self.connect(self.actionDelete, SIGNAL('triggered()'), self.removeTemplateBox) self.connect(self.actionZoom, SIGNAL('triggered()'), self.zoom) self.connect(self.actionUnzoom, SIGNAL('triggered()'), self.unzoom) self.connect(self.actionFindMatchingTemplateByOffset, SIGNAL('triggered()'), self.findMatchingTemplateByOffset) self.connect(self.actionFindMatchingTemplateByText, SIGNAL('triggered()'), self.findMatchingTemplateByText) self.connect(self.actionRecognizeInvoice, SIGNAL('triggered()'), self.recognizeInvoice) self.toggleImageBoxes() QTimer.singleShot(1000, self.setup) self.updateTitle() self.updateActions() # Login defaults LoginDialog.defaultHost = 'localhost' LoginDialog.defaultPort = 8070 LoginDialog.defaultProtocol = 'socket://' LoginDialog.defaultUserName = '******' self.recognizer = Recognizer() self.connect(self.recognizer, SIGNAL('finished()'), self.recognized)
class MainWindow(QMainWindow): Unnamed = _('unnamed') def __init__(self, parent=None): QMainWindow.__init__(self, parent) loadUi('mainwindow.ui', self) self.scene = DocumentScene() self.uiView.setScene(self.scene) self.uiView.setRenderHints(QPainter.Antialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform) self.uiView.setCacheMode(QGraphicsView.CacheBackground) self._template = Template(self.Unnamed) self.scene.setTemplate(self._template) self.uiTool = ToolWidget(self.uiToolDock) self.undoGroup = QUndoGroup(self) stack = QUndoStack(self.undoGroup) self.undoGroup.setActiveStack(stack) # Let default Qt Undo and Redo Actions handle the Undo/Redo actions # And put them at the very beggining of the Edit menu undoAction = self.undoGroup.createUndoAction(self.menuEdit) undoAction.setShortcut("Ctrl+Z") redoAction = self.undoGroup.createRedoAction(self.menuEdit) redoAction.setShortcut("Ctrl+Shift+Z") if self.menuEdit.actions(): firstAction = self.menuEdit.actions()[0] else: firstAction = None self.menuEdit.insertAction(firstAction, undoAction) self.menuEdit.insertAction(firstAction, redoAction) self.connect(self.scene, SIGNAL('newTemplateBox(QRectF)'), self.newTemplateBox) self.connect( self.scene, SIGNAL('currentTemplateBoxChanged(PyQt_PyObject,PyQt_PyObject)'), self.currentTemplateBoxChanged) self.connect(self.scene, SIGNAL('mouseMoved'), self.sceneMouseMoved) self.connect(self.actionExit, SIGNAL('triggered()'), self.close) self.connect(self.actionOpenImage, SIGNAL('triggered()'), self.openImage) self.connect(self.actionOpenTemplate, SIGNAL('triggered()'), self.openTemplate) self.connect(self.actionToggleImageBoxes, SIGNAL('triggered()'), self.toggleImageBoxes) self.connect(self.actionToggleTemplateBoxes, SIGNAL('triggered()'), self.toggleTemplateBoxes) self.connect(self.actionToggleFeatureBoxes, SIGNAL('triggered()'), self.toggleFeatureBoxes) self.connect(self.actionToggleBinarized, SIGNAL('triggered()'), self.toggleBinarized) self.connect(self.actionLogin, SIGNAL('triggered()'), self.login) self.connect(self.actionSaveTemplate, SIGNAL('triggered()'), self.saveTemplate) self.connect(self.actionSaveTemplateAs, SIGNAL('triggered()'), self.saveTemplateAs) self.connect(self.actionNewTemplate, SIGNAL('triggered()'), self.newTemplate) self.connect(self.actionDelete, SIGNAL('triggered()'), self.removeTemplateBox) self.connect(self.actionZoom, SIGNAL('triggered()'), self.zoom) self.connect(self.actionUnzoom, SIGNAL('triggered()'), self.unzoom) self.connect(self.actionFindMatchingTemplateByOffset, SIGNAL('triggered()'), self.findMatchingTemplateByOffset) self.connect(self.actionFindMatchingTemplateByText, SIGNAL('triggered()'), self.findMatchingTemplateByText) self.connect(self.actionRecognizeInvoice, SIGNAL('triggered()'), self.recognizeInvoice) self.toggleImageBoxes() QTimer.singleShot(1000, self.setup) self.updateTitle() self.updateActions() # Login defaults LoginDialog.defaultHost = 'localhost' LoginDialog.defaultPort = 8070 LoginDialog.defaultProtocol = 'socket://' LoginDialog.defaultUserName = '******' self.recognizer = Recognizer() self.connect(self.recognizer, SIGNAL('finished()'), self.recognized) def setup(self): #initOcrSystem() #self.scene.setDocument( 'c-0.tif' ) self.connect(self.uiTool, SIGNAL('recognizerChanged(QString)'), self.recognizerChanged) self.uiTool.show() self.uiToolDock.setWidget(self.uiTool) #Rpc.session.login( 'http://*****:*****@127.0.0.1:8069', 'g1' ) def sceneMouseMoved(self, pos): self.updatePosition(pos) def findMatchingTemplateByOffset(self): self.findMatchingTemplate('offset') def findMatchingTemplateByText(self): self.findMatchingTemplate('text') def recognizeInvoice(self): from NanScan.Generics.InvoiceRecognizer import InvoiceRecognizer p = InvoiceRecognizer() result = p.recognize(self.recognizer) QMessageBox.information(self, _('Invoice Recognition'), result) def findMatchingTemplate(self, type): if type == 'offset': title = _('Template search by offset') else: title = _('Template search by text') if not self.recognizer.image: QMessageBox.information( self, title, _('No image opened. Please open an image to find a matching template.' )) return if not Rpc.session.logged(): if not self.login(): return templates = TemplateStorageManager.loadAll() time = QTime() time.start() if type == 'offset': result = self.recognizer.findMatchingTemplateByOffset(templates) else: result = self.recognizer.findMatchingTemplateByText(templates) elapsed = time.elapsed() if not result['template']: QMessageBox.information( self, title, _('No template found for the current image. Took %d milliseconds' ) % elapsed) return self._template = result['template'] self.scene.setTemplate(self._template) self.updateTitle() QMessageBox.information( self, title, _('Template found with offset (%.2f, %.2f) in %d milliseconds') % (result['xOffset'], result['yOffset'], elapsed)) def recognizerChanged(self, recognizer): rect = self.uiTool.box.rect self.uiTool.setText( self.scene.recognizer.textInRegion(rect, unicode(recognizer))) def newTemplateBox(self, rect): # Creating and adding the box to the template # will automatically create the Rect in the Scene box = TemplateBox() box.rect = rect box.text = self.scene.recognizer.textInRegion(rect, 'text') box.featureRect = self.scene.recognizer.featureRectInRegion( rect, 'text') add = AddTemplateBoxUndoCommand(self._template, box) self.undoGroup.activeStack().push(add) #def setCurrentTemplateBox(self, box): #if self.uiTool.box: #self.uiTool.store() #self.uiTool.box = box def currentTemplateBoxChanged(self, current, previous): if self.uiTool.box: self.uiTool.store() self.uiTool.box = current self.actionDelete.setEnabled(bool(current)) def openImage(self): self.fileName = QFileDialog.getOpenFileName(self) if self.fileName.isNull(): return QApplication.setOverrideCursor(Qt.BusyCursor) self.recognizer.startRecognition(QImage(self.fileName)) def recognized(self): self.scene.setDocument(self.recognizer) QApplication.restoreOverrideCursor() def toggleImageBoxes(self): self.scene.setImageBoxesVisible( self.actionToggleImageBoxes.isChecked()) def toggleTemplateBoxes(self): self.scene.setTemplateBoxesVisible( self.actionToggleTemplateBoxes.isChecked()) def toggleFeatureBoxes(self): self.scene.setFeatureBoxesVisible( self.actionToggleFeatureBoxes.isChecked()) def toggleBinarized(self): self.scene.setBinarizedVisible(self.actionToggleBinarized.isChecked()) def removeTemplateBox(self): if not self.uiTool.box: return delete = DeleteUndoCommand(self._template, self.uiTool.box) self.undoGroup.activeStack().push(delete) def zoom(self): self.uiView.scale(1.2, 1.2) def unzoom(self): self.uiView.scale(0.8, 0.8) def login(self): dialog = LoginDialog(self) if dialog.exec_() == QDialog.Rejected: return False if Rpc.session.login(dialog.url, dialog.databaseName) > 0: self.updateTitle() return True else: self.updateTitle() return False def newTemplate(self): answer = QMessageBox.question( self, _('New Template'), _('Do you want to save changes to the current template?'), QMessageBox.Save | QMessageBox.No | QMessageBox.Cancel) if answer == QMessageBox.Cancel: return elif answer == QMessageBox.Save: if not self.saveTemplate(): return self._template = Template(self.Unnamed) self.scene.setTemplate(self._template) self.updateTitle() def saveTemplate(self): self.uiTool.store() if not Rpc.session.logged(): if not self.login(): return False if not self._template.id: (name, ok) = QInputDialog.getText(self, _('Save template'), _('Template name:')) if not ok: return False self._template.name = unicode(name) if self._template.id: Rpc.session.call('/object', 'execute', 'nan.template', 'write', [self._template.id], {'name': self._template.name}) ids = Rpc.session.call('/object', 'execute', 'nan.template.box', 'search', [('template', '=', self._template.id)]) Rpc.session.call('/object', 'execute', 'nan.template.box', 'unlink', ids) else: self._template.id = Rpc.session.call('/object', 'execute', 'nan.template', 'create', {'name': self._template.name}) for x in self._template.boxes: values = { 'x': x.rect.x(), 'y': x.rect.y(), 'width': x.rect.width(), 'height': x.rect.height(), 'feature_x': x.featureRect.x(), 'feature_y': x.featureRect.y(), 'feature_width': x.featureRect.width(), 'feature_height': x.featureRect.height(), 'template': self._template.id, 'name': x.name, 'text': x.text, 'recognizer': x.recognizer, 'type': x.type, 'filter': x.filter } Rpc.session.call('/object', 'execute', 'nan.template.box', 'create', values) self.updateTitle() return True def saveTemplateAs(self): id = self._template.id self._template.id = 0 if not self.saveTemplate(): self._template.id = id self.updateTitle() def openTemplate(self): if not Rpc.session.logged(): if not self.login(): return dialog = OpenTemplateDialog(self) if dialog.exec_() == QDialog.Rejected: return model = dialog.group[dialog.id] self._template = Template(model.value('name')) self._template.id = model.id fields = Rpc.session.execute('/object', 'execute', 'nan.template.box', 'fields_get') model.value('boxes').addFields(fields) for x in model.value('boxes'): box = TemplateBox() box.rect = QRectF(x.value('x'), x.value('y'), x.value('width'), x.value('height')) box.featureRect = QRectF(x.value('feature_x'), x.value('feature_y'), x.value('feature_width'), x.value('feature_height')) box.name = x.value('name') box.text = x.value('text') box.recognizer = x.value('recognizer') box.type = x.value('type') box.filter = x.value('filter') self._template.addBox(box) self.scene.setTemplate(self._template) self.updateTitle() def updateTitle(self): self.setWindowTitle("Planta - [%s]" % self._template.name) if Rpc.session.logged(): server = '%s [%s]' % (Rpc.session.url, Rpc.session.databaseName) else: shortcut = unicode(self.actionLogin.shortcut().toString()) if shortcut: server = _('Press %s to login') % shortcut else: server = 'not logged in' self.uiServer.setText(server) def updatePosition(self, pos): pos = self.uiView.mapToScene(self.uiView.mapFromGlobal(QCursor.pos())) pos = self.scene.mapPointToRecognizer(pos) position = _('(%.2f, %.2f)') % (pos.x(), pos.y()) self.uiPosition.setText(position) def updateActions(self): # Allow deleting if there's a TemplateBox selected self.actionDelete.setEnabled(bool(self.uiTool.box))
def __init__(self, parent=None): QMainWindow.__init__(self, parent) loadUi( 'mainwindow.ui', self ) self.scene = DocumentScene() self.uiView.setScene( self.scene ) self.uiView.setRenderHints( QPainter.Antialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform ) self.uiView.setCacheMode( QGraphicsView.CacheBackground ) self._template = Template( self.Unnamed ) self.scene.setTemplate(self._template) self.uiTool = ToolWidget( self.uiToolDock ) self.undoGroup = QUndoGroup( self ) stack = QUndoStack( self.undoGroup ) self.undoGroup.setActiveStack( stack ) # Let default Qt Undo and Redo Actions handle the Undo/Redo actions # And put them at the very beggining of the Edit menu undoAction = self.undoGroup.createUndoAction( self.menuEdit ) undoAction.setShortcut( "Ctrl+Z" ) redoAction = self.undoGroup.createRedoAction( self.menuEdit ) redoAction.setShortcut( "Ctrl+Shift+Z" ) if self.menuEdit.actions(): firstAction = self.menuEdit.actions()[0] else: firstAction = None self.menuEdit.insertAction( firstAction, undoAction ) self.menuEdit.insertAction( firstAction, redoAction ) self.connect( self.scene, SIGNAL('newTemplateBox(QRectF)'), self.newTemplateBox ) self.connect( self.scene, SIGNAL('currentTemplateBoxChanged(PyQt_PyObject,PyQt_PyObject)'), self.currentTemplateBoxChanged) self.connect( self.scene, SIGNAL('mouseMoved'), self.sceneMouseMoved ) self.connect( self.actionExit, SIGNAL('triggered()'), self.close ) self.connect( self.actionOpenImage, SIGNAL('triggered()'), self.openImage ) self.connect( self.actionOpenTemplate, SIGNAL('triggered()'), self.openTemplate ) self.connect( self.actionToggleImageBoxes, SIGNAL('triggered()'), self.toggleImageBoxes ) self.connect( self.actionToggleTemplateBoxes, SIGNAL('triggered()'), self.toggleTemplateBoxes ) self.connect( self.actionToggleFeatureBoxes, SIGNAL('triggered()'), self.toggleFeatureBoxes ) self.connect( self.actionToggleBinarized, SIGNAL('triggered()'), self.toggleBinarized ) self.connect( self.actionLogin, SIGNAL('triggered()'), self.login ) self.connect( self.actionSaveTemplate, SIGNAL('triggered()'), self.saveTemplate ) self.connect( self.actionSaveTemplateAs, SIGNAL('triggered()'), self.saveTemplateAs ) self.connect( self.actionNewTemplate, SIGNAL('triggered()'), self.newTemplate ) self.connect( self.actionDelete, SIGNAL('triggered()'), self.removeTemplateBox ) self.connect( self.actionZoom, SIGNAL('triggered()'), self.zoom ) self.connect( self.actionUnzoom, SIGNAL('triggered()'), self.unzoom ) self.connect( self.actionFindMatchingTemplateByOffset, SIGNAL('triggered()'), self.findMatchingTemplateByOffset ) self.connect( self.actionFindMatchingTemplateByText, SIGNAL('triggered()'), self.findMatchingTemplateByText ) self.connect( self.actionRecognizeInvoice, SIGNAL('triggered()'), self.recognizeInvoice ) self.toggleImageBoxes() QTimer.singleShot( 1000, self.setup ) self.updateTitle() self.updateActions() # Login defaults LoginDialog.defaultHost = 'localhost' LoginDialog.defaultPort = 8070 LoginDialog.defaultProtocol = 'socket://' LoginDialog.defaultUserName = '******' self.recognizer = Recognizer() self.connect( self.recognizer, SIGNAL('finished()'), self.recognized )
class MainWindow(QMainWindow): Unnamed = _('unnamed') def __init__(self, parent=None): QMainWindow.__init__(self, parent) loadUi( 'mainwindow.ui', self ) self.scene = DocumentScene() self.uiView.setScene( self.scene ) self.uiView.setRenderHints( QPainter.Antialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform ) self.uiView.setCacheMode( QGraphicsView.CacheBackground ) self._template = Template( self.Unnamed ) self.scene.setTemplate(self._template) self.uiTool = ToolWidget( self.uiToolDock ) self.undoGroup = QUndoGroup( self ) stack = QUndoStack( self.undoGroup ) self.undoGroup.setActiveStack( stack ) # Let default Qt Undo and Redo Actions handle the Undo/Redo actions # And put them at the very beggining of the Edit menu undoAction = self.undoGroup.createUndoAction( self.menuEdit ) undoAction.setShortcut( "Ctrl+Z" ) redoAction = self.undoGroup.createRedoAction( self.menuEdit ) redoAction.setShortcut( "Ctrl+Shift+Z" ) if self.menuEdit.actions(): firstAction = self.menuEdit.actions()[0] else: firstAction = None self.menuEdit.insertAction( firstAction, undoAction ) self.menuEdit.insertAction( firstAction, redoAction ) self.connect( self.scene, SIGNAL('newTemplateBox(QRectF)'), self.newTemplateBox ) self.connect( self.scene, SIGNAL('currentTemplateBoxChanged(PyQt_PyObject,PyQt_PyObject)'), self.currentTemplateBoxChanged) self.connect( self.scene, SIGNAL('mouseMoved'), self.sceneMouseMoved ) self.connect( self.actionExit, SIGNAL('triggered()'), self.close ) self.connect( self.actionOpenImage, SIGNAL('triggered()'), self.openImage ) self.connect( self.actionOpenTemplate, SIGNAL('triggered()'), self.openTemplate ) self.connect( self.actionToggleImageBoxes, SIGNAL('triggered()'), self.toggleImageBoxes ) self.connect( self.actionToggleTemplateBoxes, SIGNAL('triggered()'), self.toggleTemplateBoxes ) self.connect( self.actionToggleFeatureBoxes, SIGNAL('triggered()'), self.toggleFeatureBoxes ) self.connect( self.actionToggleBinarized, SIGNAL('triggered()'), self.toggleBinarized ) self.connect( self.actionLogin, SIGNAL('triggered()'), self.login ) self.connect( self.actionSaveTemplate, SIGNAL('triggered()'), self.saveTemplate ) self.connect( self.actionSaveTemplateAs, SIGNAL('triggered()'), self.saveTemplateAs ) self.connect( self.actionNewTemplate, SIGNAL('triggered()'), self.newTemplate ) self.connect( self.actionDelete, SIGNAL('triggered()'), self.removeTemplateBox ) self.connect( self.actionZoom, SIGNAL('triggered()'), self.zoom ) self.connect( self.actionUnzoom, SIGNAL('triggered()'), self.unzoom ) self.connect( self.actionFindMatchingTemplateByOffset, SIGNAL('triggered()'), self.findMatchingTemplateByOffset ) self.connect( self.actionFindMatchingTemplateByText, SIGNAL('triggered()'), self.findMatchingTemplateByText ) self.connect( self.actionRecognizeInvoice, SIGNAL('triggered()'), self.recognizeInvoice ) self.toggleImageBoxes() QTimer.singleShot( 1000, self.setup ) self.updateTitle() self.updateActions() # Login defaults LoginDialog.defaultHost = 'localhost' LoginDialog.defaultPort = 8070 LoginDialog.defaultProtocol = 'socket://' LoginDialog.defaultUserName = '******' self.recognizer = Recognizer() self.connect( self.recognizer, SIGNAL('finished()'), self.recognized ) def setup(self): #initOcrSystem() #self.scene.setDocument( 'c-0.tif' ) self.connect( self.uiTool, SIGNAL('recognizerChanged(QString)'), self.recognizerChanged ) self.uiTool.show() self.uiToolDock.setWidget( self.uiTool ) #Rpc.session.login( 'http://*****:*****@127.0.0.1:8069', 'g1' ) def sceneMouseMoved(self, pos): self.updatePosition( pos ) def findMatchingTemplateByOffset(self): self.findMatchingTemplate( 'offset' ) def findMatchingTemplateByText(self): self.findMatchingTemplate( 'text' ) def recognizeInvoice(self): from NanScan.Generics.InvoiceRecognizer import InvoiceRecognizer p = InvoiceRecognizer() result = p.recognize( self.recognizer ) QMessageBox.information( self, _('Invoice Recognition'), result ) def findMatchingTemplate(self, type): if type == 'offset': title = _('Template search by offset') else: title = _('Template search by text') if not self.recognizer.image: QMessageBox.information( self, title, _('No image opened. Please open an image to find a matching template.') ) return if not Rpc.session.logged(): if not self.login(): return templates = TemplateStorageManager.loadAll() time = QTime() time.start() if type == 'offset': result = self.recognizer.findMatchingTemplateByOffset( templates ) else: result = self.recognizer.findMatchingTemplateByText( templates ) elapsed = time.elapsed() if not result['template']: QMessageBox.information( self, title, _('No template found for the current image. Took %d milliseconds') % elapsed ) return self._template = result['template'] self.scene.setTemplate(self._template) self.updateTitle() QMessageBox.information( self, title, _('Template found with offset (%.2f, %.2f) in %d milliseconds') % (result['xOffset'], result['yOffset'], elapsed) ) def recognizerChanged(self, recognizer): rect = self.uiTool.box.rect self.uiTool.setText( self.scene.recognizer.textInRegion( rect, unicode(recognizer) ) ) def newTemplateBox(self, rect): # Creating and adding the box to the template # will automatically create the Rect in the Scene box = TemplateBox() box.rect = rect box.text = self.scene.recognizer.textInRegion( rect, 'text' ) box.featureRect = self.scene.recognizer.featureRectInRegion( rect, 'text' ) add = AddTemplateBoxUndoCommand( self._template, box ) self.undoGroup.activeStack().push( add ) #def setCurrentTemplateBox(self, box): #if self.uiTool.box: #self.uiTool.store() #self.uiTool.box = box def currentTemplateBoxChanged(self, current, previous): if self.uiTool.box: self.uiTool.store() self.uiTool.box = current self.actionDelete.setEnabled( bool(current) ) def openImage(self): self.fileName = QFileDialog.getOpenFileName( self ) if self.fileName.isNull(): return QApplication.setOverrideCursor( Qt.BusyCursor ) self.recognizer.startRecognition( QImage(self.fileName) ) def recognized(self): self.scene.setDocument( self.recognizer ) QApplication.restoreOverrideCursor() def toggleImageBoxes(self): self.scene.setImageBoxesVisible( self.actionToggleImageBoxes.isChecked() ) def toggleTemplateBoxes(self): self.scene.setTemplateBoxesVisible( self.actionToggleTemplateBoxes.isChecked() ) def toggleFeatureBoxes(self): self.scene.setFeatureBoxesVisible( self.actionToggleFeatureBoxes.isChecked() ) def toggleBinarized(self): self.scene.setBinarizedVisible( self.actionToggleBinarized.isChecked() ) def removeTemplateBox(self): if not self.uiTool.box: return delete = DeleteUndoCommand( self._template, self.uiTool.box ) self.undoGroup.activeStack().push( delete ) def zoom(self): self.uiView.scale( 1.2, 1.2 ) def unzoom(self): self.uiView.scale( 0.8, 0.8 ) def login(self): dialog = LoginDialog( self ) if dialog.exec_() == QDialog.Rejected: return False if Rpc.session.login( dialog.url, dialog.databaseName ) > 0: self.updateTitle() return True else: self.updateTitle() return False def newTemplate(self): answer = QMessageBox.question(self, _('New Template'), _('Do you want to save changes to the current template?'), QMessageBox.Save | QMessageBox.No | QMessageBox.Cancel ) if answer == QMessageBox.Cancel: return elif answer == QMessageBox.Save: if not self.saveTemplate(): return self._template = Template( self.Unnamed ) self.scene.setTemplate( self._template ) self.updateTitle() def saveTemplate(self): self.uiTool.store() if not Rpc.session.logged(): if not self.login(): return False if not self._template.id: (name, ok) = QInputDialog.getText( self, _('Save template'), _('Template name:') ) if not ok: return False self._template.name = unicode(name) if self._template.id: Rpc.session.call( '/object', 'execute', 'nan.template', 'write', [self._template.id], {'name': self._template.name } ) ids = Rpc.session.call( '/object', 'execute', 'nan.template.box', 'search', [('template','=',self._template.id)] ) Rpc.session.call( '/object', 'execute', 'nan.template.box', 'unlink', ids ) else: self._template.id = Rpc.session.call( '/object', 'execute', 'nan.template', 'create', {'name': self._template.name } ) for x in self._template.boxes: values = { 'x': x.rect.x(), 'y': x.rect.y(), 'width': x.rect.width(), 'height': x.rect.height(), 'feature_x' : x.featureRect.x(), 'feature_y' : x.featureRect.y(), 'feature_width' : x.featureRect.width(), 'feature_height' : x.featureRect.height(), 'template': self._template.id, 'name': x.name, 'text': x.text, 'recognizer': x.recognizer, 'type': x.type, 'filter': x.filter } Rpc.session.call( '/object', 'execute', 'nan.template.box', 'create', values ) self.updateTitle() return True def saveTemplateAs(self): id = self._template.id self._template.id = 0 if not self.saveTemplate(): self._template.id = id self.updateTitle() def openTemplate(self): if not Rpc.session.logged(): if not self.login(): return dialog = OpenTemplateDialog(self) if dialog.exec_() == QDialog.Rejected: return model = dialog.group[dialog.id] self._template = Template( model.value('name') ) self._template.id = model.id fields = Rpc.session.execute('/object', 'execute', 'nan.template.box', 'fields_get') model.value('boxes').addFields( fields ) for x in model.value('boxes'): box = TemplateBox() box.rect = QRectF( x.value('x'), x.value('y'), x.value('width'), x.value('height') ) box.featureRect = QRectF( x.value('feature_x'), x.value('feature_y'), x.value('feature_width'), x.value('feature_height') ) box.name = x.value('name') box.text = x.value('text') box.recognizer = x.value('recognizer') box.type = x.value('type') box.filter = x.value('filter') self._template.addBox( box ) self.scene.setTemplate(self._template) self.updateTitle() def updateTitle(self): self.setWindowTitle( "Planta - [%s]" % self._template.name ) if Rpc.session.logged(): server = '%s [%s]' % (Rpc.session.url, Rpc.session.databaseName) else: shortcut = unicode( self.actionLogin.shortcut().toString() ) if shortcut: server = _('Press %s to login') % shortcut else: server = 'not logged in' self.uiServer.setText( server ) def updatePosition(self, pos): pos = self.uiView.mapToScene( self.uiView.mapFromGlobal( QCursor.pos() ) ) pos = self.scene.mapPointToRecognizer( pos ) position = _('(%.2f, %.2f)') % (pos.x(), pos.y()) self.uiPosition.setText( position ) def updateActions(self): # Allow deleting if there's a TemplateBox selected self.actionDelete.setEnabled( bool(self.uiTool.box) )