Loading ballontranslator/ui/canvas.py +31 −3 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ class CustomGV(QGraphicsView): view_resized = Signal() hide_canvas = Signal() ctrl_released = Signal() canvas: QGraphicsScene = None def wheelEvent(self, event : QWheelEvent) -> None: # qgraphicsview always scroll content according to wheelevent Loading @@ -48,10 +49,18 @@ class CustomGV(QGraphicsView): self.ctrl_released.emit() return super().keyReleaseEvent(event) def keyPressEvent(self, event: QKeyEvent) -> None: if event.key() == Qt.Key.Key_Control: def keyPressEvent(self, e: QKeyEvent) -> None: if e.key() == Qt.Key.Key_Control: self.ctrl_pressed = True return super().keyPressEvent(event) if e.modifiers() == Qt.KeyboardModifier.ControlModifier: if e.key() == Qt.Key.Key_V: # self.ctrlv_pressed.emit(e) if self.canvas.handle_ctrlv(): e.accept() return return super().keyPressEvent(e) def resizeEvent(self, event: QResizeEvent) -> None: self.view_resized.emit() Loading @@ -70,6 +79,7 @@ class Canvas(QGraphicsScene): scalefactor_changed = Signal() end_create_textblock = Signal(QRectF) paste2selected_textitems = Signal() end_create_rect = Signal(QRectF, int) finish_painting = Signal(StrokeImgItem) finish_erasing = Signal(StrokeImgItem) Loading Loading @@ -112,6 +122,7 @@ class Canvas(QGraphicsScene): self.gv.view_resized.connect(self.onViewResized) self.gv.hide_canvas.connect(self.on_hide_canvas) self.gv.setRenderHint(QPainter.RenderHint.Antialiasing) self.gv.canvas = self if not C.FLAG_QT6: # mitigate https://bugreports.qt.io/browse/QTBUG-93417 Loading Loading @@ -355,6 +366,23 @@ class Canvas(QGraphicsScene): return super().mouseMoveEvent(event) def selected_text_items(self) -> List[TextBlkItem]: sel_titem = [] selitems = self.selectedItems() for sel in selitems: if isinstance(sel, TextBlkItem): sel_titem.append(sel) return sel_titem def handle_ctrlv(self) -> bool: if not self.textEditMode(): return False if self.editing_textblkitem is not None and self.editing_textblkitem.isEditing(): return False self.paste2selected_textitems.emit() return True def mousePressEvent(self, event: QGraphicsSceneMouseEvent) -> None: btn = event.button() if btn == Qt.MouseButton.MiddleButton: Loading ballontranslator/ui/scenetext_manager.py +10 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ from .canvas import Canvas from .textedit_area import TextPanel, TransTextEdit, SourceTextEdit, TransPairWidget from .fontformatpanel import set_textblk_fontsize from .misc import FontFormat, ProgramConfig, pt2px from .textedit_commands import propagate_user_edit, TextEditCommand, ReshapeItemCommand, MoveBlkItemsCommand, AutoLayoutCommand, ApplyFontformatCommand, ApplyEffectCommand, RotateItemCommand, TextItemEditCommand, TextEditCommand, PageReplaceOneCommand, PageReplaceAllCommand from .textedit_commands import propagate_user_edit, TextEditCommand, ReshapeItemCommand, MoveBlkItemsCommand, AutoLayoutCommand, ApplyFontformatCommand, ApplyEffectCommand, RotateItemCommand, TextItemEditCommand, TextEditCommand, PageReplaceOneCommand, PageReplaceAllCommand, MultiPasteCommand from utils.imgproc_utils import extract_ballon_region from utils.text_processing import seg_text, is_cjk from utils.text_layout import layout_text Loading Loading @@ -149,6 +149,7 @@ class SceneTextManager(QObject): self.canvas = canvas self.canvas.scalefactor_changed.connect(self.adjustSceneTextRect) 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.format_textblks.connect(self.onFormatTextblks) self.canvas.layout_textblks.connect(self.onAutoLayoutTextblks) Loading Loading @@ -597,6 +598,14 @@ class SceneTextManager(QObject): blk_item.set_fontformat(self.formatpanel.global_format) self.canvas.push_undo_command(CreateItemCommand(blk_item, self)) def on_paste2selected_textitems(self): blkitems = self.canvas.selected_text_items() text = self.app.clipboard().text() if len(blkitems) < 1 or not text: return etrans = [self.pairwidget_list[blkitem.idx].e_trans for blkitem in blkitems] self.canvas.push_undo_command(MultiPasteCommand(text, blkitems, etrans)) def onRotateTextBlkItem(self, item: TextBlock): self.canvas.push_undo_command(RotateItemCommand(item)) Loading ballontranslator/ui/textedit_commands.py +25 −1 Original line number Diff line number Diff line Loading @@ -443,3 +443,27 @@ class GlobalRepalceAllCommand(QUndoCommand): for src_dict in self.src_list: blk: TextBlock = self.proj.pages[trans_dict['pagename']][trans_dict['idx']] blk.text = trans_dict['ori'] class MultiPasteCommand(QUndoCommand): def __init__(self, text: str, blkitems: List[TextBlkItem], etrans: List[TransTextEdit]) -> None: super().__init__() self.op_counter = -1 self.blkitems = blkitems self.etrans = etrans for blkitem, etran in zip(self.blkitems, self.etrans): etran.setPlainTextAndKeepUndoStack(text) blkitem.setPlainTextAndKeepUndoStack(text) def redo(self): if self.op_counter == 0: self.op_counter += 1 return for blkitem, etran in zip(self.blkitems, self.etrans): blkitem.redo() etran.redo() def undo(self): for blkitem, etran in zip(self.blkitems, self.etrans): blkitem.undo() etran.undo() No newline at end of file ballontranslator/ui/textitem.py +6 −1 Original line number Diff line number Diff line Loading @@ -762,3 +762,8 @@ class TextBlkItem(QGraphicsTextItem): self.setPadding(self.layout.max_font_size(to_px=True)) if repaint: self.repaint_background() def setPlainTextAndKeepUndoStack(self, text: str): cursor = QTextCursor(self.document()) cursor.select(QTextCursor.SelectionType.Document) cursor.insertText(text) No newline at end of file Loading
ballontranslator/ui/canvas.py +31 −3 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ class CustomGV(QGraphicsView): view_resized = Signal() hide_canvas = Signal() ctrl_released = Signal() canvas: QGraphicsScene = None def wheelEvent(self, event : QWheelEvent) -> None: # qgraphicsview always scroll content according to wheelevent Loading @@ -48,10 +49,18 @@ class CustomGV(QGraphicsView): self.ctrl_released.emit() return super().keyReleaseEvent(event) def keyPressEvent(self, event: QKeyEvent) -> None: if event.key() == Qt.Key.Key_Control: def keyPressEvent(self, e: QKeyEvent) -> None: if e.key() == Qt.Key.Key_Control: self.ctrl_pressed = True return super().keyPressEvent(event) if e.modifiers() == Qt.KeyboardModifier.ControlModifier: if e.key() == Qt.Key.Key_V: # self.ctrlv_pressed.emit(e) if self.canvas.handle_ctrlv(): e.accept() return return super().keyPressEvent(e) def resizeEvent(self, event: QResizeEvent) -> None: self.view_resized.emit() Loading @@ -70,6 +79,7 @@ class Canvas(QGraphicsScene): scalefactor_changed = Signal() end_create_textblock = Signal(QRectF) paste2selected_textitems = Signal() end_create_rect = Signal(QRectF, int) finish_painting = Signal(StrokeImgItem) finish_erasing = Signal(StrokeImgItem) Loading Loading @@ -112,6 +122,7 @@ class Canvas(QGraphicsScene): self.gv.view_resized.connect(self.onViewResized) self.gv.hide_canvas.connect(self.on_hide_canvas) self.gv.setRenderHint(QPainter.RenderHint.Antialiasing) self.gv.canvas = self if not C.FLAG_QT6: # mitigate https://bugreports.qt.io/browse/QTBUG-93417 Loading Loading @@ -355,6 +366,23 @@ class Canvas(QGraphicsScene): return super().mouseMoveEvent(event) def selected_text_items(self) -> List[TextBlkItem]: sel_titem = [] selitems = self.selectedItems() for sel in selitems: if isinstance(sel, TextBlkItem): sel_titem.append(sel) return sel_titem def handle_ctrlv(self) -> bool: if not self.textEditMode(): return False if self.editing_textblkitem is not None and self.editing_textblkitem.isEditing(): return False self.paste2selected_textitems.emit() return True def mousePressEvent(self, event: QGraphicsSceneMouseEvent) -> None: btn = event.button() if btn == Qt.MouseButton.MiddleButton: Loading
ballontranslator/ui/scenetext_manager.py +10 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ from .canvas import Canvas from .textedit_area import TextPanel, TransTextEdit, SourceTextEdit, TransPairWidget from .fontformatpanel import set_textblk_fontsize from .misc import FontFormat, ProgramConfig, pt2px from .textedit_commands import propagate_user_edit, TextEditCommand, ReshapeItemCommand, MoveBlkItemsCommand, AutoLayoutCommand, ApplyFontformatCommand, ApplyEffectCommand, RotateItemCommand, TextItemEditCommand, TextEditCommand, PageReplaceOneCommand, PageReplaceAllCommand from .textedit_commands import propagate_user_edit, TextEditCommand, ReshapeItemCommand, MoveBlkItemsCommand, AutoLayoutCommand, ApplyFontformatCommand, ApplyEffectCommand, RotateItemCommand, TextItemEditCommand, TextEditCommand, PageReplaceOneCommand, PageReplaceAllCommand, MultiPasteCommand from utils.imgproc_utils import extract_ballon_region from utils.text_processing import seg_text, is_cjk from utils.text_layout import layout_text Loading Loading @@ -149,6 +149,7 @@ class SceneTextManager(QObject): self.canvas = canvas self.canvas.scalefactor_changed.connect(self.adjustSceneTextRect) 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.format_textblks.connect(self.onFormatTextblks) self.canvas.layout_textblks.connect(self.onAutoLayoutTextblks) Loading Loading @@ -597,6 +598,14 @@ class SceneTextManager(QObject): blk_item.set_fontformat(self.formatpanel.global_format) self.canvas.push_undo_command(CreateItemCommand(blk_item, self)) def on_paste2selected_textitems(self): blkitems = self.canvas.selected_text_items() text = self.app.clipboard().text() if len(blkitems) < 1 or not text: return etrans = [self.pairwidget_list[blkitem.idx].e_trans for blkitem in blkitems] self.canvas.push_undo_command(MultiPasteCommand(text, blkitems, etrans)) def onRotateTextBlkItem(self, item: TextBlock): self.canvas.push_undo_command(RotateItemCommand(item)) Loading
ballontranslator/ui/textedit_commands.py +25 −1 Original line number Diff line number Diff line Loading @@ -443,3 +443,27 @@ class GlobalRepalceAllCommand(QUndoCommand): for src_dict in self.src_list: blk: TextBlock = self.proj.pages[trans_dict['pagename']][trans_dict['idx']] blk.text = trans_dict['ori'] class MultiPasteCommand(QUndoCommand): def __init__(self, text: str, blkitems: List[TextBlkItem], etrans: List[TransTextEdit]) -> None: super().__init__() self.op_counter = -1 self.blkitems = blkitems self.etrans = etrans for blkitem, etran in zip(self.blkitems, self.etrans): etran.setPlainTextAndKeepUndoStack(text) blkitem.setPlainTextAndKeepUndoStack(text) def redo(self): if self.op_counter == 0: self.op_counter += 1 return for blkitem, etran in zip(self.blkitems, self.etrans): blkitem.redo() etran.redo() def undo(self): for blkitem, etran in zip(self.blkitems, self.etrans): blkitem.undo() etran.undo() No newline at end of file
ballontranslator/ui/textitem.py +6 −1 Original line number Diff line number Diff line Loading @@ -762,3 +762,8 @@ class TextBlkItem(QGraphicsTextItem): self.setPadding(self.layout.max_font_size(to_px=True)) if repaint: self.repaint_background() def setPlainTextAndKeepUndoStack(self, text: str): cursor = QTextCursor(self.document()) cursor.select(QTextCursor.SelectionType.Document) cursor.insertText(text) No newline at end of file