def __init__(self, parent=None):
        """ Constructor
        """
        super(MainWindow, self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)
        QApplication.setStyle(QStyleFactory.create('cleanlooks'))
        self.setupUi(self)
        self.scene = CustomGraphicsScene()
        self.connect(self.scene, SIGNAL("dropped_to_scene(QString)"), self.load_image)
        
        self.graphicsView.setScene(self.scene)
        self.scene.installEventFilter(self)
        self.graphicsView.setBackgroundBrush(QBrush(Qt.gray, Qt.BDiagPattern))
        quit_icon = QApplication.style().standardIcon(
                        QStyle.SP_DialogCloseButton)
        self.pushButtonQuit.setIcon(quit_icon)
        self.setWindowTitle('Analyze & ORC image with tesseract and leptonica')
        self.actionZoomOut.triggered.connect(self.zoomOut)
        self.actionZoomIn.triggered.connect(self.zoomIn)
        self.actionZoomTo1.triggered.connect(self.zoomTo1)
        self.connect(self.actionZoomFit, SIGNAL('triggered()'), self.zoomFit)

        # Initialize variables and pointers
        self.box_data = []
        self.pix_image = False
        self.image_width = 0
        self.image_height = 0
        self.tesseract = None
        self.api = None
        self.lang = 'eng'

        lang = sett.readSetting('language')
        if lang:
            self.lang = lang

        self.initialize_tesseract()
        if self.tesseract:
            available_languages = tess.get_list_of_langs(self.tesseract,
                                                         self.api)
            for lang in available_languages:
                self.comboBoxLang.addItem(lang, lang)
            current_index = self.comboBoxLang.findData(self.lang)
            if current_index:
                self.comboBoxLang.setCurrentIndex(current_index)

        for idx, psm in enumerate(tess.PSM):
            self.comboBoxPSM.addItem(psm, idx)
        for idx, ril in enumerate(tess.RIL):
            self.comboBoxRIL.addItem(ril, idx)

        self.leptonica = lept.get_leptonica()
        if not self.leptonica:
            self.show_msg('Leptonica initialization failed...')

        # Read settings and set default values
        geometry = sett.readSetting('settings_geometry')
        if geometry is not None:
            self.restoreGeometry(QVariant(geometry).toByteArray())
        else:
            self.resize(1150, 950)
        state = sett.readSetting('state')
        if state is not None:
            self.restoreState(QVariant(state).toByteArray())
        sp_1_state = sett.readSetting('splitter_1Sizes')
        if sp_1_state is not None:
            self.splitter_1.restoreState(QVariant(sp_1_state).toByteArray())
        sp_2_state = sett.readSetting('splitter_2Sizes')
        if sp_2_state is not None:
            self.splitter_2.restoreState(QVariant(sp_2_state).toByteArray())
        psm = sett.readSetting('PSM')
        if psm:
            current_index = self.comboBoxPSM.findData(psm)
            self.comboBoxPSM.setCurrentIndex(current_index)
        ril = sett.readSetting('RIL')
        if ril:
            current_index = self.comboBoxRIL.findData(ril)
            self.comboBoxRIL.setCurrentIndex(current_index)

        image_name = sett.readSetting('images/last_filename')
        if image_name:
            self.image_name = image_name
        self.load_image(image_name)
        zoom_factor = sett.readSetting('images/zoom_factor')
        self.setZoom(zoom_factor)
    def __init__(self, parent=None):
        """ Constructor
        """
        super(MainWindow, self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)
        QApplication.setStyle(QStyleFactory.create('cleanlooks'))
        self.setupUi(self)
        self.scene = CustomGraphicsScene()
        self.connect(self.scene, SIGNAL("dropped_to_scene(QString)"),
                     self.load_image)
        self.graphicsView.setScene(self.scene)
        self.scene.installEventFilter(self)
        self.graphicsView.setBackgroundBrush(QBrush(Qt.gray, Qt.BDiagPattern))
        quit_icon = QApplication.style().standardIcon(
            QStyle.SP_DialogCloseButton)
        self.pushButtonQuit.setIcon(quit_icon)
        self.setWindowTitle('Analyze & ORC image with tesseract and leptonica')
        self.actionZoomOut.triggered.connect(self.zoomOut)
        self.actionZoomIn.triggered.connect(self.zoomIn)
        self.actionZoomTo1.triggered.connect(self.zoomTo1)
        self.connect(self.actionZoomFit, SIGNAL('triggered()'), self.zoomFit)

        # Initialize variables and pointers
        self.box_data = []
        self.pix_image = False
        self.image_width = 0
        self.image_height = 0
        self.tesseract = None
        self.api = None
        self.lang = 'eng'

        lang = sett.readSetting('language')
        if lang:
            self.lang = lang

        self.initialize_tesseract()
        if self.tesseract:
            available_languages = tess.get_list_of_langs(
                self.tesseract, self.api)
            for lang in available_languages:
                self.comboBoxLang.addItem(lang, lang)
            current_index = self.comboBoxLang.findData(self.lang)
            if current_index:
                self.comboBoxLang.setCurrentIndex(current_index)

        for idx, psm in enumerate(tess.PSM):
            self.comboBoxPSM.addItem(psm, idx)
        for idx, ril in enumerate(tess.RIL):
            self.comboBoxRIL.addItem(ril, idx)

        self.leptonica = lept.get_leptonica()
        if not self.leptonica:
            self.show_msg('Leptonica initialization failed...')

        # Read settings and set default values
        geometry = sett.readSetting('settings_geometry')
        if geometry is not None:
            self.restoreGeometry(QVariant(geometry).toByteArray())
        else:
            self.resize(1150, 950)
        state = sett.readSetting('state')
        if state is not None:
            self.restoreState(QVariant(state).toByteArray())
        sp_1_state = sett.readSetting('splitter_1Sizes')
        if sp_1_state is not None:
            self.splitter_1.restoreState(QVariant(sp_1_state).toByteArray())
        sp_2_state = sett.readSetting('splitter_2Sizes')
        if sp_2_state is not None:
            self.splitter_2.restoreState(QVariant(sp_2_state).toByteArray())
        psm = sett.readSetting('PSM')
        if psm:
            current_index = self.comboBoxPSM.findData(psm)
            self.comboBoxPSM.setCurrentIndex(current_index)
        ril = sett.readSetting('RIL')
        if ril:
            current_index = self.comboBoxRIL.findData(ril)
            self.comboBoxRIL.setCurrentIndex(current_index)

        image_name = sett.readSetting('images/last_filename')
        if image_name:
            self.image_name = image_name
        self.load_image(image_name)
        zoom_factor = sett.readSetting('images/zoom_factor')
        self.setZoom(zoom_factor)
class MainWindow(QMainWindow, Ui_MainWindow):
    """Class For MainWindow
    """
    def __init__(self, parent=None):
        """ Constructor
        """
        super(MainWindow, self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)
        QApplication.setStyle(QStyleFactory.create('cleanlooks'))
        self.setupUi(self)
        self.scene = CustomGraphicsScene()
        self.connect(self.scene, SIGNAL("dropped_to_scene(QString)"), self.load_image)
        
        self.graphicsView.setScene(self.scene)
        self.scene.installEventFilter(self)
        self.graphicsView.setBackgroundBrush(QBrush(Qt.gray, Qt.BDiagPattern))
        quit_icon = QApplication.style().standardIcon(
                        QStyle.SP_DialogCloseButton)
        self.pushButtonQuit.setIcon(quit_icon)
        self.setWindowTitle('Analyze & ORC image with tesseract and leptonica')
        self.actionZoomOut.triggered.connect(self.zoomOut)
        self.actionZoomIn.triggered.connect(self.zoomIn)
        self.actionZoomTo1.triggered.connect(self.zoomTo1)
        self.connect(self.actionZoomFit, SIGNAL('triggered()'), self.zoomFit)

        # Initialize variables and pointers
        self.box_data = []
        self.pix_image = False
        self.image_width = 0
        self.image_height = 0
        self.tesseract = None
        self.api = None
        self.lang = 'eng'

        lang = sett.readSetting('language')
        if lang:
            self.lang = lang

        self.initialize_tesseract()
        if self.tesseract:
            available_languages = tess.get_list_of_langs(self.tesseract,
                                                         self.api)
            for lang in available_languages:
                self.comboBoxLang.addItem(lang, lang)
            current_index = self.comboBoxLang.findData(self.lang)
            if current_index:
                self.comboBoxLang.setCurrentIndex(current_index)

        for idx, psm in enumerate(tess.PSM):
            self.comboBoxPSM.addItem(psm, idx)
        for idx, ril in enumerate(tess.RIL):
            self.comboBoxRIL.addItem(ril, idx)

        self.leptonica = lept.get_leptonica()
        if not self.leptonica:
            self.show_msg('Leptonica initialization failed...')

        # Read settings and set default values
        geometry = sett.readSetting('settings_geometry')
        if geometry is not None:
            self.restoreGeometry(QVariant(geometry).toByteArray())
        else:
            self.resize(1150, 950)
        state = sett.readSetting('state')
        if state is not None:
            self.restoreState(QVariant(state).toByteArray())
        sp_1_state = sett.readSetting('splitter_1Sizes')
        if sp_1_state is not None:
            self.splitter_1.restoreState(QVariant(sp_1_state).toByteArray())
        sp_2_state = sett.readSetting('splitter_2Sizes')
        if sp_2_state is not None:
            self.splitter_2.restoreState(QVariant(sp_2_state).toByteArray())
        psm = sett.readSetting('PSM')
        if psm:
            current_index = self.comboBoxPSM.findData(psm)
            self.comboBoxPSM.setCurrentIndex(current_index)
        ril = sett.readSetting('RIL')
        if ril:
            current_index = self.comboBoxRIL.findData(ril)
            self.comboBoxRIL.setCurrentIndex(current_index)

        image_name = sett.readSetting('images/last_filename')
        if image_name:
            self.image_name = image_name
        self.load_image(image_name)
        zoom_factor = sett.readSetting('images/zoom_factor')
        self.setZoom(zoom_factor)


    def initialize_tesseract(self):
        """Create tesseract api
        """
        self.tesseract = tess.get_tesseract(os.path.dirname(__file__))
        if not self.tesseract:
            self.show_msg('Tesseract initialization failed...')
            return
        self.api = self.tesseract.TessBaseAPICreate()
        tessdata_prefix = tess.get_tessdata_prefix()
        #current_locale = locale.getlocale()  # Save current locale
        # Switch to C locale to handle
        #  Error: Illegal min or max specification!
        #  "Fatal error encountered!" == NULL:Error:Assert failed:in file
        #   ../../tesseract-ocr/ccutil/globaloc.cpp, line 75
        locale.setlocale(locale.LC_ALL, 'C')
        retc = self.tesseract.TessBaseAPIInit3(self.api,
                                                   tessdata_prefix,
                                                   self.lang)
        # Restore saved locale
        # locale.setlocale(locale.LC_ALL, current_locale)
        if (retc):
            self.tesseract.TessBaseAPIDelete(self.api)
            self.show_msg('<span style="color:red">Could not initialize ' \
                         'tesseract.</span>')
            return
        self.show_msg('Tesseract %s initialized with language \'%s\'.' % \
                      (tess.VERSION, self.lang))


    @pyqtSignature('')
    def on_pushButtonShow_pressed(self):
        """Display rectangles
        """
        tessdata_prefix = tess.get_tessdata_prefix()
        locale.setlocale(locale.LC_ALL, 'C')
        retc = 0
        if self.lang != str(self.comboBoxLang.currentText()):
            self.lang = str(self.comboBoxLang.currentText())
            retc = self.tesseract.TessBaseAPIInit3(self.api,
                                                   tessdata_prefix,
                                                   self.lang)
            self.show_msg('Using language \'%s\'.' % self.lang)
        if (retc):
            self.tesseract.TessBaseAPIDelete(self.api)
            self.show_msg('<span style="color:red">Could not re-initialize ' \
                         'tesseract.</span>')
            return

        # Shut up tesseract - there could be a lot of unwanted messages
        #tesseract.TessBaseAPISetVariable(api, "debug_file", "/dev/null")

        self.tesseract.TessBaseAPIClear(self.api)
        # Set PIX structure to tesseract api
        self.tesseract.TessBaseAPISetImage2(self.api, self.pix_image)

        self.tesseract.TessBaseAPISetPageSegMode(self.api,
                                            self.comboBoxPSM.currentIndex())

        # Get info(BOXA structure) about lines(RIL_TEXTLINE) from image in api
        boxa = self.tesseract.TessBaseAPIGetComponentImages(self.api,
                                            self.comboBoxRIL.currentIndex(),
                                            1, None, None)
        if not boxa:
            self.show_msg('No component found. Try to change PSM or RIL.')
            return

        # Get info about number of items on image
        n_items = self.leptonica.boxaGetCount(boxa)
        psm = tess.PSM[self.comboBoxPSM.currentIndex()]
        ril = tess.RIL[self.comboBoxRIL.currentIndex()]
        self.show_msg('<span style="color:green">' \
                     'Found %d image components with %s and %s.</span>' % \
                     (n_items, psm, ril))

        ocr_psm = tess.PSM_SINGLE_BLOCK
        if ril == 'RIL_PARA':
            ocr_psm = tess.PSM_SINGLE_BLOCK
        elif ril == 'RIL_TEXTLINE':
            ocr_psm = tess.PSM_SINGLE_LINE
        elif ril == 'RIL_WORD':
            ocr_psm = tess.PSM_SINGLE_WORD
        elif ril == 'RIL_SYMBOL':
            ocr_psm = tess.PSM_SINGLE_CHAR
        self.tesseract.TessBaseAPISetPageSegMode(self.api, ocr_psm)

        # Set up result type (BOX structure) for leptonica function boxaGetBox
        self.leptonica.boxaGetBox.restype = lept.BOX_PTR_T
        self.leptonica.boxaGetBox.argtypes = []
        n_boxes = len(self.box_data)
        if n_boxes:
            for idx in xrange(n_boxes):
                self.scene.removeItem(self.box_data[idx])

        # Display items and print its info
        box_items = []
        for item in range(0, n_items):
            lept_box = self.leptonica.boxaGetBox(boxa, item, lept.L_CLONE)
            box = lept_box.contents
            self.tesseract.TessBaseAPISetRectangle(self.api,
                                              box.x, box.y, box.w, box.h)
            ocr_result = self.tesseract.TessBaseAPIGetUTF8Text(self.api)
            result_text = ctypes.string_at(ocr_result).decode('utf-8').strip()
            conf = self.tesseract.TessBaseAPIMeanTextConf(self.api)
            self.show_msg('Box[%d]: x=%d, y=%d, w=%d, h=%d, ' \
                          'confidence: %d, ' \
                          'text: <span style="color:blue">%s</span>' % \
                          (item, box.x, box.y, box.w, box.h,
                           conf, result_text
                          ))
            box_items.append(self.scene.addRect(box.x, box.y, box.w, box.h,
                               QPen(QColor(255, 0, 0, 255)),
                               QBrush(QColor(255, 0, 0, 100))))
            box_items[item].setAcceptHoverEvents(True)
            box_items[item].setToolTip("Box[%d]: confidence:%s, text:%s" % \
                                      (item, conf, result_text))
        QCoreApplication.processEvents()
        self.box_data = box_items

    @pyqtSignature('')
    def on_pushButtonLoad_pressed(self):
        """Load Image
        """
        input_dir = sett.readSetting('images/input_dir')
        image = QFileDialog.getOpenFileName(self,
                    u'打开图片文件',
                    input_dir,
                    'Images (*.jpg *.jpeg *.bmp *.png *.tiff *.tif *.gif);;' \
                    'All files (*.*)')

        if not image:
            self.show_msg(u'未选择文件…')
            return
        self.load_image(image)
        sett.storeSetting('images/input_dir', os.path.dirname(str(image)));

    @pyqtSignature('')
    def on_pushButtonRestart_pressed(self):
        """Restart program
        """
        python = sys.executable
        os.execl(python, python, * sys.argv)

    def load_image(self, filename):
        "Load image to scene and create PIX"
        self.scene.clear()
        self.zoomTo1()
        self.image_name = str(filename)  # filename must be c-string
        # Read image with leptonica => create PIX structure and report image
        # size info
        self.pix_image = self.leptonica.pixRead(self.image_name)
        self.image_width = self.leptonica.pixGetWidth(self.pix_image)
        self.image_height = self.leptonica.pixGetHeight(self.pix_image)
        self.show_msg("image size: %dx%d, resolution %dx%d" % \
                     (self.image_width,
                      self.image_height,
                      self.leptonica.pixGetXRes(self.pix_image),
                      self.leptonica.pixGetYRes(self.pix_image)
                     ))
        self.box_data = []
        qimage = lept.pix_to_qimage(self.leptonica, self.pix_image)
        if not qimage:  # fallback solution
            self.scene.addPixmap(QPixmap(filename))
        else:
            self.scene.addPixmap(QPixmap(qimage))
        self.setWindowTitle('Analyze & ORC image with tesseract and ' \
                            'leptonica :: %s' % os.path.basename(self.image_name))

    def show_msg(self, message):
        """Show message in textBrowser
        """
        self.textEdit.append(message)
        # Scroll to end of the last message
        cursor = QTextCursor(self.textEdit.textCursor())
        cursor.movePosition(QTextCursor.End)
        self.textEdit.setTextCursor(cursor)
        QApplication.processEvents()

    def closeEvent(self, event):
        """Store setting on exit
        """
        sett.storeSetting('geometry', self.saveGeometry())
        sett.storeSetting('state', self.saveState())
        sett.storeSetting("splitter_1Sizes", self.splitter_1.saveState());
        sett.storeSetting("splitter_1Geo", self.splitter_1.saveGeometry());
        sett.storeSetting("splitter_2Sizes", self.splitter_2.saveState());
        sett.storeSetting('images/last_filename', self.image_name)
        sett.storeSetting('images/zoom_factor', self.getZoomFactor())
        row_l = self.comboBoxLang.currentIndex()
        lang = self.comboBoxLang.itemData(row_l).toString()
        if lang:
            sett.storeSetting('language', lang)
        row_p = self.comboBoxPSM.currentIndex()
        sett.storeSetting('PSM',
                          self.comboBoxPSM.itemData(row_p).toString())
        row_r = self.comboBoxRIL.currentIndex()
        sett.storeSetting('RIL',
                          self.comboBoxRIL.itemData(row_r).toString())
        QMainWindow.closeEvent(self, event)

    def setZoom(self, scale):
        """Scale to selected factor
        """
        transform = QTransform()
        transform.scale(scale, scale)
        self.graphicsView.setTransform(transform)

    def zoomFit(self):
        """Zoom image to fit in graphicsView window
        """
        # put border to preferencies
        border = 0.95
        if (not self.image_height) or (not self.image_width):
            return
        viewWidth = self.graphicsView.viewport().width() * border
        viewHeight = self.graphicsView.viewport().height() * border

        ratio = float(viewWidth / viewHeight)
        aspectRatio = float(self.image_width / self.image_height)

        if ratio > aspectRatio:
            zoomFactor = float(viewHeight / self.image_height)
        else:
            zoomFactor = float(viewWidth / self.image_width)
        self.setZoom(zoomFactor)

    def zoomTo1(self):
        """Zoom to 1:1
        """
        self.setZoom(1)

    def zoomIn(self):
        """Zoom In
        """
        factor = 1.25
        self.graphicsView.scale(factor, factor)

    def zoomOut(self):
        """Zoom Out
        """
        factor = .8
        self.graphicsView.scale(factor, factor)
        self.getZoomFactor()

    def getZoomFactor(self):
        """Get current zoom factor
        """
        return self.graphicsView.transform().m11()

    def eventFilter(self, obj, event):
        """Zoom In/Out with CTRL + mouse wheel
        """
        if event.type() == QEvent.GraphicsSceneWheel:
            assert isinstance(obj, QGraphicsScene)
            delta = event.delta()
            if (event.modifiers() == Qt.ControlModifier and delta > 0):
                factor = 1.41 ** (event.delta() / 240.0)
                self.graphicsView.scale(factor, factor)
                event.accept()
                return True
            elif (event.modifiers() == Qt.ControlModifier and delta < 0):
                factor = 1.41 ** (event.delta() / 240.0)
                self.graphicsView.scale(factor, factor)
                event.accept()
                return True
        return obj.eventFilter(obj, event)
class MainWindow(QMainWindow, Ui_MainWindow):
    """Class For MainWindow
    """
    def __init__(self, parent=None):
        """ Constructor
        """
        super(MainWindow, self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)
        QApplication.setStyle(QStyleFactory.create('cleanlooks'))
        self.setupUi(self)
        self.scene = CustomGraphicsScene()
        self.connect(self.scene, SIGNAL("dropped_to_scene(QString)"),
                     self.load_image)
        self.graphicsView.setScene(self.scene)
        self.scene.installEventFilter(self)
        self.graphicsView.setBackgroundBrush(QBrush(Qt.gray, Qt.BDiagPattern))
        quit_icon = QApplication.style().standardIcon(
            QStyle.SP_DialogCloseButton)
        self.pushButtonQuit.setIcon(quit_icon)
        self.setWindowTitle('Analyze & ORC image with tesseract and leptonica')
        self.actionZoomOut.triggered.connect(self.zoomOut)
        self.actionZoomIn.triggered.connect(self.zoomIn)
        self.actionZoomTo1.triggered.connect(self.zoomTo1)
        self.connect(self.actionZoomFit, SIGNAL('triggered()'), self.zoomFit)

        # Initialize variables and pointers
        self.box_data = []
        self.pix_image = False
        self.image_width = 0
        self.image_height = 0
        self.tesseract = None
        self.api = None
        self.lang = 'eng'

        lang = sett.readSetting('language')
        if lang:
            self.lang = lang

        self.initialize_tesseract()
        if self.tesseract:
            available_languages = tess.get_list_of_langs(
                self.tesseract, self.api)
            for lang in available_languages:
                self.comboBoxLang.addItem(lang, lang)
            current_index = self.comboBoxLang.findData(self.lang)
            if current_index:
                self.comboBoxLang.setCurrentIndex(current_index)

        for idx, psm in enumerate(tess.PSM):
            self.comboBoxPSM.addItem(psm, idx)
        for idx, ril in enumerate(tess.RIL):
            self.comboBoxRIL.addItem(ril, idx)

        self.leptonica = lept.get_leptonica()
        if not self.leptonica:
            self.show_msg('Leptonica initialization failed...')

        # Read settings and set default values
        geometry = sett.readSetting('settings_geometry')
        if geometry is not None:
            self.restoreGeometry(QVariant(geometry).toByteArray())
        else:
            self.resize(1150, 950)
        state = sett.readSetting('state')
        if state is not None:
            self.restoreState(QVariant(state).toByteArray())
        sp_1_state = sett.readSetting('splitter_1Sizes')
        if sp_1_state is not None:
            self.splitter_1.restoreState(QVariant(sp_1_state).toByteArray())
        sp_2_state = sett.readSetting('splitter_2Sizes')
        if sp_2_state is not None:
            self.splitter_2.restoreState(QVariant(sp_2_state).toByteArray())
        psm = sett.readSetting('PSM')
        if psm:
            current_index = self.comboBoxPSM.findData(psm)
            self.comboBoxPSM.setCurrentIndex(current_index)
        ril = sett.readSetting('RIL')
        if ril:
            current_index = self.comboBoxRIL.findData(ril)
            self.comboBoxRIL.setCurrentIndex(current_index)

        image_name = sett.readSetting('images/last_filename')
        if image_name:
            self.image_name = image_name
        self.load_image(image_name)
        zoom_factor = sett.readSetting('images/zoom_factor')
        self.setZoom(zoom_factor)

    def initialize_tesseract(self):
        """Create tesseract api
        """
        self.tesseract = tess.get_tesseract(os.path.dirname(__file__))
        if not self.tesseract:
            self.show_msg('Tesseract initialization failed...')
            return
        self.api = self.tesseract.TessBaseAPICreate()
        tessdata_prefix = tess.get_tessdata_prefix()
        #current_locale = locale.getlocale()  # Save current locale
        # Switch to C locale to handle
        #  Error: Illegal min or max specification!
        #  "Fatal error encountered!" == NULL:Error:Assert failed:in file
        #   ../../tesseract-ocr/ccutil/globaloc.cpp, line 75
        locale.setlocale(locale.LC_ALL, 'C')
        retc = self.tesseract.TessBaseAPIInit3(self.api, tessdata_prefix,
                                               self.lang)
        # Restore saved locale
        # locale.setlocale(locale.LC_ALL, current_locale)
        if (retc):
            self.tesseract.TessBaseAPIDelete(self.api)
            self.show_msg('<span style="color:red">Could not initialize ' \
                         'tesseract.</span>')
            return
        self.show_msg('Tesseract %s initialized with language \'%s\'.' % \
                      (tess.VERSION, self.lang))

    @pyqtSignature('')
    def on_pushButtonShow_pressed(self):
        """Display rectangles
        """
        tessdata_prefix = tess.get_tessdata_prefix()
        locale.setlocale(locale.LC_ALL, 'C')
        retc = 0
        if self.lang != str(self.comboBoxLang.currentText()):
            self.lang = str(self.comboBoxLang.currentText())
            retc = self.tesseract.TessBaseAPIInit3(self.api, tessdata_prefix,
                                                   self.lang)
            self.show_msg('Using language \'%s\'.' % self.lang)
        if (retc):
            self.tesseract.TessBaseAPIDelete(self.api)
            self.show_msg('<span style="color:red">Could not re-initialize ' \
                         'tesseract.</span>')
            return

        # Shut up tesseract - there could be a lot of unwanted messages
        #tesseract.TessBaseAPISetVariable(api, "debug_file", "/dev/null")

        self.tesseract.TessBaseAPIClear(self.api)
        # Set PIX structure to tesseract api
        self.tesseract.TessBaseAPISetImage2(self.api, self.pix_image)

        self.tesseract.TessBaseAPISetPageSegMode(
            self.api, self.comboBoxPSM.currentIndex())

        # Get info(BOXA structure) about lines(RIL_TEXTLINE) from image in api
        boxa = self.tesseract.TessBaseAPIGetComponentImages(
            self.api, self.comboBoxRIL.currentIndex(), 1, None, None)
        if not boxa:
            self.show_msg('No component found. Try to change PSM or RIL.')
            return

        # Get info about number of items on image
        n_items = self.leptonica.boxaGetCount(boxa)
        psm = tess.PSM[self.comboBoxPSM.currentIndex()]
        ril = tess.RIL[self.comboBoxRIL.currentIndex()]
        self.show_msg('<span style="color:green">' \
                     'Found %d image components with %s and %s.</span>' % \
                     (n_items, psm, ril))

        ocr_psm = tess.PSM_SINGLE_BLOCK
        if ril == 'RIL_PARA':
            ocr_psm = tess.PSM_SINGLE_BLOCK
        elif ril == 'RIL_TEXTLINE':
            ocr_psm = tess.PSM_SINGLE_LINE
        elif ril == 'RIL_WORD':
            ocr_psm = tess.PSM_SINGLE_WORD
        elif ril == 'RIL_SYMBOL':
            ocr_psm = tess.PSM_SINGLE_CHAR
        self.tesseract.TessBaseAPISetPageSegMode(self.api, ocr_psm)

        # Set up result type (BOX structure) for leptonica function boxaGetBox
        self.leptonica.boxaGetBox.restype = lept.BOX_PTR_T
        self.leptonica.boxaGetBox.argtypes = []
        n_boxes = len(self.box_data)
        if n_boxes:
            for idx in xrange(n_boxes):
                self.scene.removeItem(self.box_data[idx])

        # Display items and print its info
        box_items = []
        for item in range(0, n_items):
            lept_box = self.leptonica.boxaGetBox(boxa, item, lept.L_CLONE)
            box = lept_box.contents
            self.tesseract.TessBaseAPISetRectangle(self.api, box.x, box.y,
                                                   box.w, box.h)
            ocr_result = self.tesseract.TessBaseAPIGetUTF8Text(self.api)
            result_text = ctypes.string_at(ocr_result).decode('utf-8').strip()
            conf = self.tesseract.TessBaseAPIMeanTextConf(self.api)
            self.show_msg('Box[%d]: x=%d, y=%d, w=%d, h=%d, ' \
                          'confidence: %d, ' \
                          'text: <span style="color:blue">%s</span>' % \
                          (item, box.x, box.y, box.w, box.h,
                           conf, result_text
                          ))
            box_items.append(
                self.scene.addRect(box.x, box.y, box.w, box.h,
                                   QPen(QColor(255, 0, 0, 255)),
                                   QBrush(QColor(255, 0, 0, 100))))
            box_items[item].setAcceptHoverEvents(True)
            box_items[item].setToolTip("Box[%d]: confidence:%s, text:%s" % \
                                      (item, conf, result_text))
        QCoreApplication.processEvents()
        self.box_data = box_items

    @pyqtSignature('')
    def on_pushButtonLoad_pressed(self):
        """Load Image
        """
        input_dir = sett.readSetting('images/input_dir')
        image = QFileDialog.getOpenFileName(self,
                    'Open Image file',
                    input_dir,
                    'Images (*.jpg *.jpeg *.bmp *.png *.tiff *.tif *.gif);;' \
                    'All files (*.*)')

        if not image:
            self.show_msg(u'File was not selected…')
            return
        self.load_image(image)
        sett.storeSetting('images/input_dir', os.path.dirname(str(image)))

    @pyqtSignature('')
    def on_pushButtonRestart_pressed(self):
        """Restart program
        """
        python = sys.executable
        os.execl(python, python, *sys.argv)

    def load_image(self, filename):
        """Load image to scene and create PIX
        """
        self.scene.clear()
        self.zoomTo1()
        self.image_name = str(filename)  # filename must be c-string
        # Read image with leptonica => create PIX structure and report image
        # size info
        self.pix_image = self.leptonica.pixRead(self.image_name)
        self.image_width = self.leptonica.pixGetWidth(self.pix_image)
        self.image_height = self.leptonica.pixGetHeight(self.pix_image)
        self.show_msg("image size: %dx%d, resolution %dx%d" % \
                     (self.image_width,
                      self.image_height,
                      self.leptonica.pixGetXRes(self.pix_image),
                      self.leptonica.pixGetYRes(self.pix_image)
                     ))
        self.box_data = []
        qimage = lept.pix_to_qimage(self.leptonica, self.pix_image)
        if not qimage:  # fallback solution
            self.scene.addPixmap(QPixmap(filename))
        else:
            self.scene.addPixmap(QPixmap(qimage))
        self.setWindowTitle('Analyze & ORC image with tesseract and ' \
                            'leptonica :: %s' % os.path.basename(self.image_name))

    def show_msg(self, message):
        """Show message in textBrowser
        """
        self.textEdit.append(message)
        # Scroll to end of the last message
        cursor = QTextCursor(self.textEdit.textCursor())
        cursor.movePosition(QTextCursor.End)
        self.textEdit.setTextCursor(cursor)
        QApplication.processEvents()

    def closeEvent(self, event):
        """Store setting on exit
        """
        sett.storeSetting('geometry', self.saveGeometry())
        sett.storeSetting('state', self.saveState())
        sett.storeSetting("splitter_1Sizes", self.splitter_1.saveState())
        sett.storeSetting("splitter_1Geo", self.splitter_1.saveGeometry())
        sett.storeSetting("splitter_2Sizes", self.splitter_2.saveState())
        sett.storeSetting('images/last_filename', self.image_name)
        sett.storeSetting('images/zoom_factor', self.getZoomFactor())
        row_l = self.comboBoxLang.currentIndex()
        lang = self.comboBoxLang.itemData(row_l).toString()
        if lang:
            sett.storeSetting('language', lang)
        row_p = self.comboBoxPSM.currentIndex()
        sett.storeSetting('PSM', self.comboBoxPSM.itemData(row_p).toString())
        row_r = self.comboBoxRIL.currentIndex()
        sett.storeSetting('RIL', self.comboBoxRIL.itemData(row_r).toString())
        QMainWindow.closeEvent(self, event)

    def setZoom(self, scale):
        """Scale to selected factor
        """
        transform = QTransform()
        transform.scale(scale, scale)
        self.graphicsView.setTransform(transform)

    def zoomFit(self):
        """Zoom image to fit in graphicsView window
        """
        # TODO: put border to preferencies
        border = 0.95
        if (not self.image_height) or (not self.image_width):
            return
        viewWidth = self.graphicsView.viewport().width() * border
        viewHeight = self.graphicsView.viewport().height() * border

        ratio = float(viewWidth / viewHeight)
        aspectRatio = float(self.image_width / self.image_height)

        if ratio > aspectRatio:
            zoomFactor = float(viewHeight / self.image_height)
        else:
            zoomFactor = float(viewWidth / self.image_width)
        self.setZoom(zoomFactor)

    def zoomTo1(self):
        """Zoom to 1:1
        """
        self.setZoom(1)

    def zoomIn(self):
        """Zoom In
        """
        factor = 1.25
        self.graphicsView.scale(factor, factor)

    def zoomOut(self):
        """Zoom Out
        """
        factor = .8
        self.graphicsView.scale(factor, factor)
        self.getZoomFactor()

    def getZoomFactor(self):
        """Get current zoom factor
        """
        return self.graphicsView.transform().m11()

    def eventFilter(self, obj, event):
        """Zoom In/Out with CTRL + mouse wheel
        """
        if event.type() == QEvent.GraphicsSceneWheel:
            assert isinstance(obj, QGraphicsScene)
            delta = event.delta()
            if (event.modifiers() == Qt.ControlModifier and delta > 0):
                factor = 1.41**(event.delta() / 240.0)
                self.graphicsView.scale(factor, factor)
                event.accept()
                return True
            elif (event.modifiers() == Qt.ControlModifier and delta < 0):
                factor = 1.41**(event.delta() / 240.0)
                self.graphicsView.scale(factor, factor)
                event.accept()
                return True
        return obj.eventFilter(obj, event)