Loading ballontranslator/dl/textdetector/textblock.py +9 −0 Original line number Diff line number Diff line Loading @@ -286,6 +286,15 @@ class TextBlock(object): return self.default_stroke_width return 0 def adjust_pos(self, dx: int, dy: int): self.xyxy[0] += dx self.xyxy[1] += dy self.xyxy[2] += dx self.xyxy[3] += dy if self._bounding_rect is not None: self._bounding_rect[0] += dx self._bounding_rect[1] += dy def sort_textblk_list(blk_list: List[TextBlock], im_w: int, im_h: int) -> List[TextBlock]: if len(blk_list) == 0: return blk_list Loading ballontranslator/ui/canvas.py +37 −3 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ from typing import List, Union, Tuple from qtpy.QtWidgets import QMenu, QGraphicsScene, QGraphicsView, QGraphicsRectItem, QGraphicsItem, QScrollBar, QGraphicsPixmapItem, QGraphicsSceneMouseEvent, QGraphicsSceneContextMenuEvent, QRubberBand from qtpy.QtCore import Qt, QDateTime, QRectF, QPointF, QPoint, Signal, QSizeF, QEvent from qtpy.QtGui import QPixmap, QHideEvent, QKeyEvent, QWheelEvent, QResizeEvent, QPainter, QPen, QPainterPath from qtpy.QtGui import QPixmap, QHideEvent, QKeyEvent, QWheelEvent, QResizeEvent, QPainter, QPen, QPainterPath, QCursor try: from qtpy.QtWidgets import QUndoStack, QUndoCommand Loading Loading @@ -59,6 +59,10 @@ class CustomGV(QGraphicsView): if self.canvas.handle_ctrlv(): e.accept() return if e.key() == Qt.Key.Key_C: if self.canvas.handle_ctrlc(): e.accept() return return super().keyPressEvent(e) Loading @@ -84,6 +88,8 @@ class Canvas(QGraphicsScene): finish_painting = Signal(StrokeImgItem) finish_erasing = Signal(StrokeImgItem) delete_textblks = Signal() copy_textblks = Signal(QPointF) paste_textblks = Signal(QPointF) format_textblks = Signal() layout_textblks = Signal() Loading Loading @@ -188,6 +194,8 @@ class Canvas(QGraphicsScene): self.saved_textundo_step = 0 self.saved_drawundo_step = 0 self.clipboard_blks: List[TextBlock] = [] def textEditMode(self) -> bool: return self.editor_index == 1 Loading Loading @@ -380,9 +388,28 @@ class Canvas(QGraphicsScene): if self.editing_textblkitem is not None and self.editing_textblkitem.isEditing(): return False if len(self.selected_text_items()) > 0: self.paste2selected_textitems.emit() else: self.paste_textblks.emit(self.scene_cursor_pos()) return True def handle_ctrlc(self): if not self.textEditMode(): return False if self.editing_textblkitem is not None and self.editing_textblkitem.isEditing(): return False if len(self.selected_text_items()) > 0: self.copy_textblks.emit(self.scene_cursor_pos()) return True def scene_cursor_pos(self): origin = self.gv.mapFromGlobal(QCursor.pos()) return self.gv.mapToScene(origin) def mousePressEvent(self, event: QGraphicsSceneMouseEvent) -> None: btn = event.button() if btn == Qt.MouseButton.MiddleButton: Loading Loading @@ -507,14 +534,21 @@ class Canvas(QGraphicsScene): self.textblock_mode = mode def contextMenuEvent(self, event: QGraphicsSceneContextMenuEvent): if len(self.selectedItems()) != 0: if self.textEditMode(): menu = QMenu() copy_act = menu.addAction(self.tr("Copy")) paste_act = menu.addAction(self.tr("Paste")) delete_act = menu.addAction(self.tr("Delete")) menu.addSeparator() format_act = menu.addAction(self.tr("Apply font formatting")) layout_act = menu.addAction(self.tr("Auto layout")) rst = menu.exec_(event.screenPos()) if rst == delete_act: self.delete_textblks.emit() elif rst == copy_act: self.copy_textblks.emit(event.scenePos()) elif rst == paste_act: self.paste_textblks.emit(event.scenePos()) elif rst == format_act: self.format_textblks.emit() elif rst == layout_act: Loading ballontranslator/ui/scenetext_manager.py +70 −1 Original line number Diff line number Diff line from typing import List, Union, Tuple import numpy as np import copy from qtpy.QtWidgets import QApplication from qtpy.QtCore import QObject, QRectF, Qt, Signal from qtpy.QtCore import QObject, QRectF, Qt, Signal, QPointF from qtpy.QtGui import QTextCursor, QFontMetrics, QFont, QTextCharFormat try: from qtpy.QtWidgets import QUndoCommand Loading Loading @@ -137,6 +138,25 @@ class DeleteBlkItemsCommand(QUndoCommand): self.sw.updateCounterText() class PasteBlkItemsCommand(QUndoCommand): def __init__(self, blk_list: List[TextBlkItem], pwidget_list: List[TransPairWidget], ctrl, parent=None): super().__init__(parent) self.op_counter = 0 self.blk_list = blk_list for blkitem in blk_list: blkitem.setSelected(True) self.pwidget_list = pwidget_list self.ctrl:SceneTextManager = ctrl def redo(self): if self.op_counter == 0: self.op_counter += 1 return self.ctrl.recoverTextblkItemList(self.blk_list, self.pwidget_list) def undo(self): self.ctrl.deleteTextblkItemList(self.blk_list, self.pwidget_list) class SceneTextManager(QObject): new_textblk = Signal(int) def __init__(self, Loading @@ -151,6 +171,8 @@ class SceneTextManager(QObject): self.canvas.end_create_textblock.connect(self.onEndCreateTextBlock) self.canvas.paste2selected_textitems.connect(self.on_paste2selected_textitems) self.canvas.delete_textblks.connect(self.onDeleteBlkItems) self.canvas.copy_textblks.connect(self.onCopyBlkItems) self.canvas.paste_textblks.connect(self.onPasteBlkItems) self.canvas.format_textblks.connect(self.onFormatTextblks) self.canvas.layout_textblks.connect(self.onAutoLayoutTextblks) self.txtblkShapeControl = canvas.txtblkShapeControl Loading Loading @@ -383,6 +405,53 @@ class SceneTextManager(QObject): if len(selected_blks) > 0: self.canvas.push_undo_command(DeleteBlkItemsCommand(selected_blks, self)) def onCopyBlkItems(self, pos: QPointF): selected_blks = self.get_selected_blkitems() if len(selected_blks) == 0 and self.txtblkShapeControl.blk_item is not None: selected_blks.append(self.txtblkShapeControl.blk_item) if len(selected_blks) == 0: return self.canvas.clipboard_blks.clear() if self.canvas.text_change_unsaved(): self.updateTextBlkList() if pos is None: pos = selected_blks[0].blk.xyxy pos_x, pos_y = pos[0], pos[1] else: pos_x, pos_y = pos.x(), pos.y() pos_x = int(pos_x / self.canvas.scale_factor) pos_y = int(pos_y / self.canvas.scale_factor) for blkitems in selected_blks: blk = copy.deepcopy(blkitems.blk) blk.adjust_pos(-pos_x, -pos_y) self.canvas.clipboard_blks.append(blk) def onPasteBlkItems(self, pos: QPointF): if pos is None: pos_x, pos_y = 0, 0 else: pos_x, pos_y = pos.x(), pos.y() pos_x = int(pos_x / self.canvas.scale_factor) pos_y = int(pos_y / self.canvas.scale_factor) blkitem_list, pair_widget_list = [], [] for blk in self.canvas.clipboard_blks: blk = copy.deepcopy(blk) blk.adjust_pos(pos_x, pos_y) blkitem = self.addTextBlock(blk) pairw = self.pairwidget_list[-1] blkitem_list.append(blkitem) pair_widget_list.append(pairw) if len(blkitem_list) > 0: self.canvas.clearSelection() self.canvas.push_undo_command(PasteBlkItemsCommand(blkitem_list, pair_widget_list, self)) pass def onFormatTextblks(self): self.apply_fontformat(self.formatpanel.global_format) Loading Loading
ballontranslator/dl/textdetector/textblock.py +9 −0 Original line number Diff line number Diff line Loading @@ -286,6 +286,15 @@ class TextBlock(object): return self.default_stroke_width return 0 def adjust_pos(self, dx: int, dy: int): self.xyxy[0] += dx self.xyxy[1] += dy self.xyxy[2] += dx self.xyxy[3] += dy if self._bounding_rect is not None: self._bounding_rect[0] += dx self._bounding_rect[1] += dy def sort_textblk_list(blk_list: List[TextBlock], im_w: int, im_h: int) -> List[TextBlock]: if len(blk_list) == 0: return blk_list Loading
ballontranslator/ui/canvas.py +37 −3 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ from typing import List, Union, Tuple from qtpy.QtWidgets import QMenu, QGraphicsScene, QGraphicsView, QGraphicsRectItem, QGraphicsItem, QScrollBar, QGraphicsPixmapItem, QGraphicsSceneMouseEvent, QGraphicsSceneContextMenuEvent, QRubberBand from qtpy.QtCore import Qt, QDateTime, QRectF, QPointF, QPoint, Signal, QSizeF, QEvent from qtpy.QtGui import QPixmap, QHideEvent, QKeyEvent, QWheelEvent, QResizeEvent, QPainter, QPen, QPainterPath from qtpy.QtGui import QPixmap, QHideEvent, QKeyEvent, QWheelEvent, QResizeEvent, QPainter, QPen, QPainterPath, QCursor try: from qtpy.QtWidgets import QUndoStack, QUndoCommand Loading Loading @@ -59,6 +59,10 @@ class CustomGV(QGraphicsView): if self.canvas.handle_ctrlv(): e.accept() return if e.key() == Qt.Key.Key_C: if self.canvas.handle_ctrlc(): e.accept() return return super().keyPressEvent(e) Loading @@ -84,6 +88,8 @@ class Canvas(QGraphicsScene): finish_painting = Signal(StrokeImgItem) finish_erasing = Signal(StrokeImgItem) delete_textblks = Signal() copy_textblks = Signal(QPointF) paste_textblks = Signal(QPointF) format_textblks = Signal() layout_textblks = Signal() Loading Loading @@ -188,6 +194,8 @@ class Canvas(QGraphicsScene): self.saved_textundo_step = 0 self.saved_drawundo_step = 0 self.clipboard_blks: List[TextBlock] = [] def textEditMode(self) -> bool: return self.editor_index == 1 Loading Loading @@ -380,9 +388,28 @@ class Canvas(QGraphicsScene): if self.editing_textblkitem is not None and self.editing_textblkitem.isEditing(): return False if len(self.selected_text_items()) > 0: self.paste2selected_textitems.emit() else: self.paste_textblks.emit(self.scene_cursor_pos()) return True def handle_ctrlc(self): if not self.textEditMode(): return False if self.editing_textblkitem is not None and self.editing_textblkitem.isEditing(): return False if len(self.selected_text_items()) > 0: self.copy_textblks.emit(self.scene_cursor_pos()) return True def scene_cursor_pos(self): origin = self.gv.mapFromGlobal(QCursor.pos()) return self.gv.mapToScene(origin) def mousePressEvent(self, event: QGraphicsSceneMouseEvent) -> None: btn = event.button() if btn == Qt.MouseButton.MiddleButton: Loading Loading @@ -507,14 +534,21 @@ class Canvas(QGraphicsScene): self.textblock_mode = mode def contextMenuEvent(self, event: QGraphicsSceneContextMenuEvent): if len(self.selectedItems()) != 0: if self.textEditMode(): menu = QMenu() copy_act = menu.addAction(self.tr("Copy")) paste_act = menu.addAction(self.tr("Paste")) delete_act = menu.addAction(self.tr("Delete")) menu.addSeparator() format_act = menu.addAction(self.tr("Apply font formatting")) layout_act = menu.addAction(self.tr("Auto layout")) rst = menu.exec_(event.screenPos()) if rst == delete_act: self.delete_textblks.emit() elif rst == copy_act: self.copy_textblks.emit(event.scenePos()) elif rst == paste_act: self.paste_textblks.emit(event.scenePos()) elif rst == format_act: self.format_textblks.emit() elif rst == layout_act: Loading
ballontranslator/ui/scenetext_manager.py +70 −1 Original line number Diff line number Diff line from typing import List, Union, Tuple import numpy as np import copy from qtpy.QtWidgets import QApplication from qtpy.QtCore import QObject, QRectF, Qt, Signal from qtpy.QtCore import QObject, QRectF, Qt, Signal, QPointF from qtpy.QtGui import QTextCursor, QFontMetrics, QFont, QTextCharFormat try: from qtpy.QtWidgets import QUndoCommand Loading Loading @@ -137,6 +138,25 @@ class DeleteBlkItemsCommand(QUndoCommand): self.sw.updateCounterText() class PasteBlkItemsCommand(QUndoCommand): def __init__(self, blk_list: List[TextBlkItem], pwidget_list: List[TransPairWidget], ctrl, parent=None): super().__init__(parent) self.op_counter = 0 self.blk_list = blk_list for blkitem in blk_list: blkitem.setSelected(True) self.pwidget_list = pwidget_list self.ctrl:SceneTextManager = ctrl def redo(self): if self.op_counter == 0: self.op_counter += 1 return self.ctrl.recoverTextblkItemList(self.blk_list, self.pwidget_list) def undo(self): self.ctrl.deleteTextblkItemList(self.blk_list, self.pwidget_list) class SceneTextManager(QObject): new_textblk = Signal(int) def __init__(self, Loading @@ -151,6 +171,8 @@ class SceneTextManager(QObject): self.canvas.end_create_textblock.connect(self.onEndCreateTextBlock) self.canvas.paste2selected_textitems.connect(self.on_paste2selected_textitems) self.canvas.delete_textblks.connect(self.onDeleteBlkItems) self.canvas.copy_textblks.connect(self.onCopyBlkItems) self.canvas.paste_textblks.connect(self.onPasteBlkItems) self.canvas.format_textblks.connect(self.onFormatTextblks) self.canvas.layout_textblks.connect(self.onAutoLayoutTextblks) self.txtblkShapeControl = canvas.txtblkShapeControl Loading Loading @@ -383,6 +405,53 @@ class SceneTextManager(QObject): if len(selected_blks) > 0: self.canvas.push_undo_command(DeleteBlkItemsCommand(selected_blks, self)) def onCopyBlkItems(self, pos: QPointF): selected_blks = self.get_selected_blkitems() if len(selected_blks) == 0 and self.txtblkShapeControl.blk_item is not None: selected_blks.append(self.txtblkShapeControl.blk_item) if len(selected_blks) == 0: return self.canvas.clipboard_blks.clear() if self.canvas.text_change_unsaved(): self.updateTextBlkList() if pos is None: pos = selected_blks[0].blk.xyxy pos_x, pos_y = pos[0], pos[1] else: pos_x, pos_y = pos.x(), pos.y() pos_x = int(pos_x / self.canvas.scale_factor) pos_y = int(pos_y / self.canvas.scale_factor) for blkitems in selected_blks: blk = copy.deepcopy(blkitems.blk) blk.adjust_pos(-pos_x, -pos_y) self.canvas.clipboard_blks.append(blk) def onPasteBlkItems(self, pos: QPointF): if pos is None: pos_x, pos_y = 0, 0 else: pos_x, pos_y = pos.x(), pos.y() pos_x = int(pos_x / self.canvas.scale_factor) pos_y = int(pos_y / self.canvas.scale_factor) blkitem_list, pair_widget_list = [], [] for blk in self.canvas.clipboard_blks: blk = copy.deepcopy(blk) blk.adjust_pos(pos_x, pos_y) blkitem = self.addTextBlock(blk) pairw = self.pairwidget_list[-1] blkitem_list.append(blkitem) pair_widget_list.append(pairw) if len(blkitem_list) > 0: self.canvas.clearSelection() self.canvas.push_undo_command(PasteBlkItemsCommand(blkitem_list, pair_widget_list, self)) pass def onFormatTextblks(self): self.apply_fontformat(self.formatpanel.global_format) Loading