Loading modules/ocr/ocr_google_vision.py +17 −6 Original line number Diff line number Diff line Loading @@ -77,8 +77,9 @@ class OCRGoogleVisionAPI(OCRBase): try: params['delay'] = float(params['delay']) except (ValueError, TypeError): params['delay'] = 1.0 # Default value params['delay'] = 1.0 super().__init__(**params) self.proxy_url = self.proxy self.last_request_time = 0 def send_to_google_vision(self, image_buffer: bytes): Loading Loading @@ -110,21 +111,29 @@ class OCRGoogleVisionAPI(OCRBase): "Content-Type": "application/json" } proxy_url = self.proxy client_kwargs = {'headers': headers} if self.proxy_url: mounts = {} if self.proxy_url.startswith(('http://', 'https://', 'socks4://', 'socks5://')): mounts["all://"] = httpx.HTTPTransport(proxy=self.proxy_url) else: self.logger.warning("The proxy URL does not contain a schema (http://, https://, socks4://, socks5://). The proxy may not work.") mounts["all://"] = httpx.HTTPTransport(proxy=self.proxy_url) client_kwargs['mounts'] = mounts with httpx.Client(proxy=proxy_url) as client: with httpx.Client(**client_kwargs) as client: try: if self.debug_mode: self.logger.debug(f"Sending request to Google Vision API...") proxy_info = self.proxy_url if self.proxy_url else "No proxy" self.logger.debug(f"Sending request to Google Vision API with proxy: {proxy_info}") response = client.post(VISION_API_URL, headers=headers, json=request_body) response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx) response.raise_for_status() return response.json() except httpx.HTTPError as e: raise Exception(f"Error during request to Google Vision API: {e}") def extract_text_and_coordinates(self, annotations): text_with_coords = [] for annotation in annotations: Loading Loading @@ -262,3 +271,5 @@ class OCRGoogleVisionAPI(OCRBase): except (ValueError, TypeError): param_content = 1.0 super().updateParam(param_key, param_content) if param_key == 'proxy': self.proxy_url = param_content No newline at end of file ui/custom_widget/label.py +17 −8 Original line number Diff line number Diff line from typing import List, Union, Tuple import numpy as np from qtpy.QtWidgets import QGraphicsOpacityEffect, QLabel, QColorDialog from qtpy.QtWidgets import QGraphicsOpacityEffect, QLabel, QColorDialog, QMenu from qtpy.QtCore import Qt, QPropertyAnimation, QEasingCurve, Signal from qtpy.QtGui import QMouseEvent, QWheelEvent, QColor Loading Loading @@ -43,19 +43,28 @@ class FadeLabel(QLabel): class ColorPickerLabel(QLabel): colorChanged = Signal(bool) apply_color = Signal(str, tuple) changingColor = Signal() def __init__(self, parent=None, param_name='', *args, **kwargs): super().__init__(parent=parent, *args, **kwargs) self.color: QColor = None self.param_name = param_name def mousePressEvent(self, event): def mousePressEvent(self, event: QMouseEvent): btn = event.button() if btn == Qt.MouseButton.LeftButton: self.changingColor.emit() color = QColorDialog.getColor() is_valid = color.isValid() if is_valid: self.setPickerColor(color) self.colorChanged.emit(is_valid) elif btn == Qt.MouseButton.RightButton: menu = QMenu(self) apply_act = menu.addAction(self.tr("Apply Color")) rst = menu.exec(event.globalPosition().toPoint()) if rst == apply_act and self.color is not None: self.apply_color.emit(self.param_name, self.rgb()) def setPickerColor(self, color: Union[QColor, List, Tuple]): if not isinstance(color, QColor): Loading ui/fontformat_commands.py +13 −10 Original line number Diff line number Diff line Loading @@ -41,12 +41,12 @@ def wrap_fntformat_input(values: str, blkitems: List[TextBlkItem], is_global: bo values = [values] * len(blkitems) return blkitems, values def font_formating(push_undostack: bool = False): def font_formating(push_undostack: bool = False, is_property = True): def func_wrapper(formatting_func): def wrapper(param_name: str, values: str, act_ffmt: FontFormat, is_global: bool, blkitems: List[TextBlkItem] = None, set_focus: bool = False, *args, **kwargs): if is_global: if is_global and is_property: if hasattr(act_ffmt, param_name): act_ffmt[param_name] = values else: Loading @@ -54,6 +54,7 @@ def font_formating(push_undostack: bool = False): blkitems, values = wrap_fntformat_input(values, blkitems, is_global) if len(blkitems) > 0: if is_property: act_ffmt[param_name] = values[0] if push_undostack: params = copy.deepcopy(kwargs) Loading Loading @@ -142,14 +143,16 @@ def ffmt_change_stroke_width(param_name: str, values: float, act_ffmt: FontForma def ffmt_change_font_size(param_name: str, values: float, act_ffmt: FontFormat, is_global: bool, blkitems: List[TextBlkItem], clip_size=False, **kwargs): set_kwargs = global_default_set_kwargs if is_global else local_default_set_kwargs for blkitem, value in zip(blkitems, values): if value < 0 and param_name == "font_size": if value < 0: continue if param_name == "font_size": setFontSize = blkitem.setFontSize value = px2pt(value) else: setFontSize = blkitem.setRelFontSize setFontSize(value, clip_size=clip_size, **set_kwargs) blkitem.setFontSize(value, clip_size=clip_size, **set_kwargs) @font_formating(is_property=False) def ffmt_change_rel_font_size(param_name: str, values: float, act_ffmt: FontFormat, is_global: bool, blkitems: List[TextBlkItem], clip_size=False, **kwargs): set_kwargs = global_default_set_kwargs if is_global else local_default_set_kwargs for blkitem, value in zip(blkitems, values): blkitem.setRelFontSize(value, clip_size=clip_size, **set_kwargs) @font_formating(push_undostack=True) def ffmt_change_alignment(param_name: str, values: float, act_ffmt: FontFormat, is_global: bool, blkitems: List[TextBlkItem], **kwargs): Loading ui/funcmaps.py +1 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ from utils.textblock_mask import canny_flood, connected_canny_flood, existing_ma # Build base function map handle_ffmt_change = build_funcmap('ui.fontformat_commands', list(FontFormat.params().keys()), list(FontFormat.params().keys()) + ['rel_font_size'], 'ffmt_change_', verbose=False) Loading ui/mainwindow.py +10 −5 Original line number Diff line number Diff line Loading @@ -134,7 +134,7 @@ class MainWindow(mainwindow_cls): self.leftBar.globalSearchChecker.clicked.connect(self.on_set_gsearch_widget) self.leftBar.open_dir.connect(self.OpenProj) self.leftBar.open_json_proj.connect(self.openJsonProj) self.leftBar.save_proj.connect(self.save_proj) self.leftBar.save_proj.connect(self.manual_save) self.leftBar.export_doc.connect(self.on_export_doc) self.leftBar.import_doc.connect(self.on_import_doc) self.leftBar.export_src_txt.connect(lambda : self.on_export_txt(dump_target='source')) Loading Loading @@ -257,6 +257,8 @@ class MainWindow(mainwindow_cls): self.bottomBar.originalSlider.setValue(int(pcfg.original_transparency * 100)) self.drawingPanel.maskTransperancySlider.setValue(int(pcfg.mask_transparency * 100)) self.leftBar.initRecentProjMenu(pcfg.recent_proj_list) self.leftBar.showPageListLabel.setChecked(pcfg.show_page_list) self.updatePageList() self.leftBar.save_config.connect(self.save_config) self.leftBar.imgTransChecker.setChecked(True) self.st_manager.formatpanel.global_format = pcfg.global_fontformat Loading Loading @@ -443,6 +445,8 @@ class MainWindow(mainwindow_cls): self.leftStackWidget.setCurrentWidget(self.pageList) else: self.leftStackWidget.hide() pcfg.show_page_list = setup save_config() def closeEvent(self, event: QCloseEvent) -> None: self.st_manager.hovering_transwidget = None Loading Loading @@ -480,7 +484,7 @@ class MainWindow(mainwindow_cls): self.canvas.alt_pressed = False self.canvas.scale_tool_mode = False def conditional_manual_save(self): def conditional_save(self): if self.canvas.projstate_unsaved and not self.opening_dir: update_scene_text = save_proj = self.canvas.text_change_unsaved() save_rst_only = not self.canvas.draw_change_unsaved() Loading @@ -494,7 +498,7 @@ class MainWindow(mainwindow_cls): self.page_changing = True if item is not None: if self.save_on_page_changed: self.conditional_manual_save() self.conditional_save() self.imgtrans_proj.set_current_img(item.text()) self.canvas.clear_undostack(update_saved_step=True) self.canvas.updateCanvas() Loading Loading @@ -786,10 +790,11 @@ class MainWindow(mainwindow_cls): pcfg.imgtrans_textblock = mode self.st_manager.showTextblkItemRect(mode) def save_proj(self): def manual_save(self): if self.leftBar.imgTransChecker.isChecked()\ and self.imgtrans_proj.directory is not None: self.conditional_manual_save() LOGGER.debug('Manually saving...') self.saveCurrentPage(update_scene_text=True, save_proj=True, restore_interface=True, save_rst_only=False) def saveCurrentPage(self, update_scene_text=True, save_proj=True, restore_interface=False, save_rst_only=False): Loading Loading
modules/ocr/ocr_google_vision.py +17 −6 Original line number Diff line number Diff line Loading @@ -77,8 +77,9 @@ class OCRGoogleVisionAPI(OCRBase): try: params['delay'] = float(params['delay']) except (ValueError, TypeError): params['delay'] = 1.0 # Default value params['delay'] = 1.0 super().__init__(**params) self.proxy_url = self.proxy self.last_request_time = 0 def send_to_google_vision(self, image_buffer: bytes): Loading Loading @@ -110,21 +111,29 @@ class OCRGoogleVisionAPI(OCRBase): "Content-Type": "application/json" } proxy_url = self.proxy client_kwargs = {'headers': headers} if self.proxy_url: mounts = {} if self.proxy_url.startswith(('http://', 'https://', 'socks4://', 'socks5://')): mounts["all://"] = httpx.HTTPTransport(proxy=self.proxy_url) else: self.logger.warning("The proxy URL does not contain a schema (http://, https://, socks4://, socks5://). The proxy may not work.") mounts["all://"] = httpx.HTTPTransport(proxy=self.proxy_url) client_kwargs['mounts'] = mounts with httpx.Client(proxy=proxy_url) as client: with httpx.Client(**client_kwargs) as client: try: if self.debug_mode: self.logger.debug(f"Sending request to Google Vision API...") proxy_info = self.proxy_url if self.proxy_url else "No proxy" self.logger.debug(f"Sending request to Google Vision API with proxy: {proxy_info}") response = client.post(VISION_API_URL, headers=headers, json=request_body) response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx) response.raise_for_status() return response.json() except httpx.HTTPError as e: raise Exception(f"Error during request to Google Vision API: {e}") def extract_text_and_coordinates(self, annotations): text_with_coords = [] for annotation in annotations: Loading Loading @@ -262,3 +271,5 @@ class OCRGoogleVisionAPI(OCRBase): except (ValueError, TypeError): param_content = 1.0 super().updateParam(param_key, param_content) if param_key == 'proxy': self.proxy_url = param_content No newline at end of file
ui/custom_widget/label.py +17 −8 Original line number Diff line number Diff line from typing import List, Union, Tuple import numpy as np from qtpy.QtWidgets import QGraphicsOpacityEffect, QLabel, QColorDialog from qtpy.QtWidgets import QGraphicsOpacityEffect, QLabel, QColorDialog, QMenu from qtpy.QtCore import Qt, QPropertyAnimation, QEasingCurve, Signal from qtpy.QtGui import QMouseEvent, QWheelEvent, QColor Loading Loading @@ -43,19 +43,28 @@ class FadeLabel(QLabel): class ColorPickerLabel(QLabel): colorChanged = Signal(bool) apply_color = Signal(str, tuple) changingColor = Signal() def __init__(self, parent=None, param_name='', *args, **kwargs): super().__init__(parent=parent, *args, **kwargs) self.color: QColor = None self.param_name = param_name def mousePressEvent(self, event): def mousePressEvent(self, event: QMouseEvent): btn = event.button() if btn == Qt.MouseButton.LeftButton: self.changingColor.emit() color = QColorDialog.getColor() is_valid = color.isValid() if is_valid: self.setPickerColor(color) self.colorChanged.emit(is_valid) elif btn == Qt.MouseButton.RightButton: menu = QMenu(self) apply_act = menu.addAction(self.tr("Apply Color")) rst = menu.exec(event.globalPosition().toPoint()) if rst == apply_act and self.color is not None: self.apply_color.emit(self.param_name, self.rgb()) def setPickerColor(self, color: Union[QColor, List, Tuple]): if not isinstance(color, QColor): Loading
ui/fontformat_commands.py +13 −10 Original line number Diff line number Diff line Loading @@ -41,12 +41,12 @@ def wrap_fntformat_input(values: str, blkitems: List[TextBlkItem], is_global: bo values = [values] * len(blkitems) return blkitems, values def font_formating(push_undostack: bool = False): def font_formating(push_undostack: bool = False, is_property = True): def func_wrapper(formatting_func): def wrapper(param_name: str, values: str, act_ffmt: FontFormat, is_global: bool, blkitems: List[TextBlkItem] = None, set_focus: bool = False, *args, **kwargs): if is_global: if is_global and is_property: if hasattr(act_ffmt, param_name): act_ffmt[param_name] = values else: Loading @@ -54,6 +54,7 @@ def font_formating(push_undostack: bool = False): blkitems, values = wrap_fntformat_input(values, blkitems, is_global) if len(blkitems) > 0: if is_property: act_ffmt[param_name] = values[0] if push_undostack: params = copy.deepcopy(kwargs) Loading Loading @@ -142,14 +143,16 @@ def ffmt_change_stroke_width(param_name: str, values: float, act_ffmt: FontForma def ffmt_change_font_size(param_name: str, values: float, act_ffmt: FontFormat, is_global: bool, blkitems: List[TextBlkItem], clip_size=False, **kwargs): set_kwargs = global_default_set_kwargs if is_global else local_default_set_kwargs for blkitem, value in zip(blkitems, values): if value < 0 and param_name == "font_size": if value < 0: continue if param_name == "font_size": setFontSize = blkitem.setFontSize value = px2pt(value) else: setFontSize = blkitem.setRelFontSize setFontSize(value, clip_size=clip_size, **set_kwargs) blkitem.setFontSize(value, clip_size=clip_size, **set_kwargs) @font_formating(is_property=False) def ffmt_change_rel_font_size(param_name: str, values: float, act_ffmt: FontFormat, is_global: bool, blkitems: List[TextBlkItem], clip_size=False, **kwargs): set_kwargs = global_default_set_kwargs if is_global else local_default_set_kwargs for blkitem, value in zip(blkitems, values): blkitem.setRelFontSize(value, clip_size=clip_size, **set_kwargs) @font_formating(push_undostack=True) def ffmt_change_alignment(param_name: str, values: float, act_ffmt: FontFormat, is_global: bool, blkitems: List[TextBlkItem], **kwargs): Loading
ui/funcmaps.py +1 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ from utils.textblock_mask import canny_flood, connected_canny_flood, existing_ma # Build base function map handle_ffmt_change = build_funcmap('ui.fontformat_commands', list(FontFormat.params().keys()), list(FontFormat.params().keys()) + ['rel_font_size'], 'ffmt_change_', verbose=False) Loading
ui/mainwindow.py +10 −5 Original line number Diff line number Diff line Loading @@ -134,7 +134,7 @@ class MainWindow(mainwindow_cls): self.leftBar.globalSearchChecker.clicked.connect(self.on_set_gsearch_widget) self.leftBar.open_dir.connect(self.OpenProj) self.leftBar.open_json_proj.connect(self.openJsonProj) self.leftBar.save_proj.connect(self.save_proj) self.leftBar.save_proj.connect(self.manual_save) self.leftBar.export_doc.connect(self.on_export_doc) self.leftBar.import_doc.connect(self.on_import_doc) self.leftBar.export_src_txt.connect(lambda : self.on_export_txt(dump_target='source')) Loading Loading @@ -257,6 +257,8 @@ class MainWindow(mainwindow_cls): self.bottomBar.originalSlider.setValue(int(pcfg.original_transparency * 100)) self.drawingPanel.maskTransperancySlider.setValue(int(pcfg.mask_transparency * 100)) self.leftBar.initRecentProjMenu(pcfg.recent_proj_list) self.leftBar.showPageListLabel.setChecked(pcfg.show_page_list) self.updatePageList() self.leftBar.save_config.connect(self.save_config) self.leftBar.imgTransChecker.setChecked(True) self.st_manager.formatpanel.global_format = pcfg.global_fontformat Loading Loading @@ -443,6 +445,8 @@ class MainWindow(mainwindow_cls): self.leftStackWidget.setCurrentWidget(self.pageList) else: self.leftStackWidget.hide() pcfg.show_page_list = setup save_config() def closeEvent(self, event: QCloseEvent) -> None: self.st_manager.hovering_transwidget = None Loading Loading @@ -480,7 +484,7 @@ class MainWindow(mainwindow_cls): self.canvas.alt_pressed = False self.canvas.scale_tool_mode = False def conditional_manual_save(self): def conditional_save(self): if self.canvas.projstate_unsaved and not self.opening_dir: update_scene_text = save_proj = self.canvas.text_change_unsaved() save_rst_only = not self.canvas.draw_change_unsaved() Loading @@ -494,7 +498,7 @@ class MainWindow(mainwindow_cls): self.page_changing = True if item is not None: if self.save_on_page_changed: self.conditional_manual_save() self.conditional_save() self.imgtrans_proj.set_current_img(item.text()) self.canvas.clear_undostack(update_saved_step=True) self.canvas.updateCanvas() Loading Loading @@ -786,10 +790,11 @@ class MainWindow(mainwindow_cls): pcfg.imgtrans_textblock = mode self.st_manager.showTextblkItemRect(mode) def save_proj(self): def manual_save(self): if self.leftBar.imgTransChecker.isChecked()\ and self.imgtrans_proj.directory is not None: self.conditional_manual_save() LOGGER.debug('Manually saving...') self.saveCurrentPage(update_scene_text=True, save_proj=True, restore_interface=True, save_rst_only=False) def saveCurrentPage(self, update_scene_text=True, save_proj=True, restore_interface=False, save_rst_only=False): Loading