Loading ui/drawingpanel.py +1 −1 Original line number Diff line number Diff line Loading @@ -338,7 +338,7 @@ class DrawingPanel(Widget): self.setPenToolColor([0, 0, 0, 127]) self.toolConfigStackwidget = QStackedWidget() self.toolConfigStackwidget.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) self.toolConfigStackwidget.setSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Minimum) self.toolConfigStackwidget.addWidget(self.inpaintConfigPanel) self.toolConfigStackwidget.addWidget(self.penConfigPanel) self.toolConfigStackwidget.addWidget(self.rectPanel) Loading ui/fontformatpanel.py +3 −4 Original line number Diff line number Diff line Loading @@ -425,7 +425,7 @@ class TextStyleLabel(Widget): self.active_stylename_edited = active_stylename_edited self.stylelabel = StyleLabel(style_name, parent=self) self.stylelabel.edit_finished.connect(self.on_style_name_edited) self.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) self.setSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Maximum) self.setToolTip(self.tr('Click to set as Global format. Double click to edit name.')) self.setCursor(Qt.CursorShape.PointingHandCursor) Loading Loading @@ -642,8 +642,7 @@ class TextStyleArea(QScrollArea): self.flayout.addWidget(self.new_btn) self.flayout.addWidget(self.clear_btn) # self.scrollContent.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) self.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Maximum) ScrollBar(Qt.Orientation.Vertical, self) self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) Loading Loading @@ -880,7 +879,7 @@ class TextStylePanel(Widget): self.style_area.hide() self.title_label.clicked.connect(self.on_title_label_clicked) self.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Maximum) def expand(self): if not self.title_label.expanded: Loading ui/scenetext_manager.py +42 −13 Original line number Diff line number Diff line Loading @@ -248,32 +248,56 @@ class RearrangeBlksCommand(QUndoCommand): def __init__(self, rmap: Tuple, ctrl, parent=None): super().__init__(parent) self.ctrl: SceneTextManager = ctrl self.src_ids, self.tgt_ids = rmap self.src_ids, self.tgt_ids = rmap[0], rmap[1] self.nr = len(self.src_ids) self.src2tgt = {} self.tgt2src = {} for s, t in zip(self.src_ids, self.tgt_ids): self.src2tgt[s] = t self.tgt2src[t] = s self.visible_ = None self.redo_visible_idx = self.undo_visible_idx = None if len(rmap) > 2: self.redo_visible_idx, self.undo_visible_idx = rmap[2] def redo(self): self.rearrage_blk_ids(self.src_ids, self.tgt_ids) self.rearange_blk_ids(self.src_ids, self.tgt_ids, self.redo_visible_idx) def undo(self): self.rearrage_blk_ids(self.tgt_ids, self.src_ids) self.rearange_blk_ids(self.tgt_ids, self.src_ids, self.undo_visible_idx) def rearange_blk_ids(self, src_ids, tgt_ids, visible_idx = None): src_ids = np.array(src_ids) tgt_ids = np.array(tgt_ids) src_order_ids = np.argsort(src_ids)[::-1] src_ids = src_ids[src_order_ids] tgt_ids = tgt_ids[src_order_ids] def rearrage_blk_ids(self, src_ids, tgt_ids): blks: List[TextBlkItem] = [] pws: List[TransPairWidget] = [] for ii, src_idx in enumerate(src_ids): pos = src_idx - ii for pos, pos_tgt in zip(src_ids, tgt_ids): pw = self.ctrl.pairwidget_list.pop(pos) self.ctrl.textEditList.removeWidget(pw, remove_checked=False) if visible_idx == pos_tgt: pw.hide() blk = self.ctrl.textblk_item_list.pop(pos) pws.append(pw) blks.append(blk) for ii, tgt_idx in enumerate(tgt_ids): self.ctrl.textblk_item_list.insert(tgt_idx, blks[ii]) self.ctrl.pairwidget_list.insert(tgt_idx, pws[ii]) self.ctrl.textEditList.insertPairWidget(pws[ii], tgt_idx) tgt_order_ids = np.argsort(tgt_ids) for ii in tgt_order_ids: pos = tgt_ids[ii] self.ctrl.textblk_item_list.insert(pos, blks[ii]) self.ctrl.textEditList.insertPairWidget(pws[ii], pos) self.ctrl.pairwidget_list.insert(pos, pws[ii]) self.ctrl.updateTextBlkItemIdx() # some optimization could be done here self.ctrl.updateTextBlkItemIdx(set(tgt_ids)) if visible_idx is not None: pw_ct = self.ctrl.pairwidget_list[visible_idx] pw_ct.show() self.ctrl.textEditList.ensureWidgetVisible(pw_ct, yMargin=pw.height()) class TextPanel(Widget): def __init__(self, app: QApplication, *args, **kwargs) -> None: Loading Loading @@ -404,6 +428,7 @@ class SceneTextManager(QObject): pair_widget.e_trans.show_select_menu.connect(self.on_show_select_menu) pair_widget.e_trans.focus_out.connect(self.on_pairw_focusout) pair_widget.drag_move.connect(self.textEditList.handle_drag_pos) pair_widget.idx_edited.connect(self.textEditList.on_idx_edited) self.new_textblk.emit(blk_item.idx) return blk_item Loading Loading @@ -941,6 +966,7 @@ class SceneTextManager(QObject): def on_transwidget_selection_changed(self): selitems = self.canvas.selected_text_items() selset = {pw.idx: pw for pw in self.textEditList.checked_list} self.canvas.block_selection_signal = True for blkitem in selitems: if blkitem.idx not in selset: blkitem.setSelected(False) Loading @@ -948,6 +974,7 @@ class SceneTextManager(QObject): selset.pop(blkitem.idx) for idx in selset: self.textblk_item_list[idx].setSelected(True) self.canvas.block_selection_signal = False def on_textedit_list_focusout(self): fw = self.app.focusWidget() Loading @@ -966,8 +993,10 @@ class SceneTextManager(QObject): if len(selected_blks) > 0: self.canvas.push_undo_command(ApplyEffectCommand(selected_blks, ffmt)) def updateTextBlkItemIdx(self): def updateTextBlkItemIdx(self, sel_ids: set = None): for ii, blk_item in enumerate(self.textblk_item_list): if sel_ids is not None and ii not in sel_ids: continue blk_item.idx = ii self.pairwidget_list[ii].updateIndex(ii) cl = self.textEditList.checked_list Loading ui/stylewidgets.py +0 −5 Original line number Diff line number Diff line Loading @@ -529,11 +529,6 @@ class ClickableLabel(QLabel): self.clicked.emit() return super().mousePressEvent(e) class IgnoreMouseLabel(QLabel): def mousePressEvent(self, e: QMouseEvent) -> None: e.ignore() return super().mousePressEvent(e) class CheckableLabel(QLabel): Loading ui/textedit_area.py +145 −10 Original line number Diff line number Diff line from typing import List, Union from qtpy.QtWidgets import QTextEdit, QScrollArea, QGraphicsDropShadowEffect, QVBoxLayout, QApplication, QHBoxLayout, QSizePolicy from qtpy.QtCore import Signal, Qt, QMimeData, QEvent, QPoint from qtpy.QtGui import QColor, QFocusEvent, QInputMethodEvent, QDragEnterEvent, QDragMoveEvent, QDropEvent, QKeyEvent, QTextCursor, QMouseEvent, QDrag, QPixmap, QKeySequence from qtpy.QtWidgets import QStackedWidget, QSizePolicy, QTextEdit, QScrollArea, QGraphicsDropShadowEffect, QVBoxLayout, QApplication, QHBoxLayout, QSizePolicy, QLabel, QLineEdit from qtpy.QtCore import Signal, Qt, QMimeData, QEvent, QPoint, QSize from qtpy.QtGui import QIntValidator, QColor, QFocusEvent, QInputMethodEvent, QDragEnterEvent, QDragMoveEvent, QDropEvent, QKeyEvent, QTextCursor, QMouseEvent, QDrag, QPixmap, QKeySequence import keyboard import webbrowser import numpy as np from .stylewidgets import Widget, SeparatorWidget, ClickableLabel, IgnoreMouseLabel, ScrollBar from .stylewidgets import Widget, SeparatorWidget, ClickableLabel, ScrollBar from .textitem import TextBlock from utils.config import pcfg from utils.logger import logger as LOGGER STYLE_TRANSPAIR_CHECKED = "background-color: rgba(30, 147, 229, 20%);" Loading Loading @@ -304,19 +305,110 @@ class TransTextEdit(SourceTextEdit): pass class RowIndexEditor(QLineEdit): focus_out = Signal() def __init__(self, parent=None): super().__init__(parent=parent) self.setValidator(QIntValidator()) self.setReadOnly(True) self.setTextMargins(0, 0, 0, 0) def focusOutEvent(self, e: QFocusEvent) -> None: super().focusOutEvent(e) self.focus_out.emit() def minimumSizeHint(self): size = super().minimumSizeHint() return QSize(1, size.height()) def sizeHint(self): size = super().sizeHint() return QSize(1, size.height()) class RowIndexLabel(QStackedWidget): submmit_idx = Signal(int) def __init__(self, text: str = None, parent=None): super().__init__(parent=parent) self.lineedit = RowIndexEditor(parent=self) self.lineedit.focus_out.connect(self.on_lineedit_focusout) self.show_label = QLabel(self) self.text = self.show_label.text self.addWidget(self.show_label) self.addWidget(self.lineedit) self.setCurrentIndex(0) if text is not None: self.setText(text) self.setSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Maximum) def setText(self, text): if isinstance(text, int): text = str(text) self.show_label.setText(text) self.lineedit.setText(text) def keyPressEvent(self, e: QKeyEvent) -> None: super().keyPressEvent(e) key = e.key() if key == Qt.Key.Key_Return: self.try_update_idx() def try_update_idx(self): idx_str = self.lineedit.text().strip() if not idx_str: return if self.text() == idx_str: return try: idx = int(idx_str) self.lineedit.setReadOnly(True) self.submmit_idx.emit(idx) except Exception as e: LOGGER.warning(f'Invalid index str: {idx}') def mouseDoubleClickEvent(self, e: QMouseEvent) -> None: self.startEdit() return super().mouseDoubleClickEvent(e) def startEdit(self) -> None: self.setCurrentIndex(1) self.lineedit.setReadOnly(False) self.lineedit.setFocus() def on_lineedit_focusout(self): edited = not self.lineedit.isReadOnly() self.lineedit.setReadOnly(True) self.setCurrentIndex(0) if edited: self.try_update_idx() def mousePressEvent(self, e: QMouseEvent) -> None: e.ignore() return super().mousePressEvent(e) class TransPairWidget(Widget): check_state_changed = Signal(object, bool, bool) drag_move = Signal(int) idx_edited = Signal(int, int) def __init__(self, textblock: TextBlock = None, idx: int = None, fold: bool = False, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.e_source = SourceTextEdit(idx, self, fold) self.e_trans = TransTextEdit(idx, self, fold) self.idx_label = IgnoreMouseLabel(self) self.idx_label = RowIndexLabel(idx, self) self.idx_label.setText(str(idx + 1).zfill(2)) # showed index start from 1! self.submmit_idx = self.idx_label.submmit_idx.connect(self.on_idx_edited) self.textblock = textblock self.idx = idx self.checked = False Loading @@ -339,6 +431,10 @@ class TransPairWidget(Widget): self.setAcceptDrops(True) def on_idx_edited(self, new_idx: int): new_idx -= 1 self.idx_edited.emit(self.idx, new_idx) def dragEnterEvent(self, e: QDragEnterEvent) -> None: if isinstance(e.source(), TransPairWidget): e.accept() Loading Loading @@ -369,7 +465,7 @@ class TransPairWidget(Widget): else: self.setStyleSheet("") def mouseReleaseEvent(self, e: QMouseEvent) -> None: def update_checkstate_by_mousevent(self, e: QMouseEvent): if e.button() == Qt.MouseButton.LeftButton: modifiers = e.modifiers() if modifiers & Qt.KeyboardModifier.ShiftModifier and modifiers & Qt.KeyboardModifier.ControlModifier: Loading @@ -378,7 +474,11 @@ class TransPairWidget(Widget): shift_pressed = modifiers == Qt.KeyboardModifier.ShiftModifier ctrl_pressed = modifiers == Qt.KeyboardModifier.ControlModifier self.check_state_changed.emit(self, shift_pressed, ctrl_pressed) return super().mouseReleaseEvent(e) def mousePressEvent(self, e: QMouseEvent) -> None: if not self.checked: self.update_checkstate_by_mousevent(e) return super().mousePressEvent(e) def updateIndex(self, idx: int): if self.idx != idx: Loading Loading @@ -464,7 +564,21 @@ class TextEditListScrollArea(QScrollArea): new_maps = np.where(drags != new_pos) if len(new_maps) == 0: return drags_ori, drags_tgt = drags[new_maps], new_pos[new_maps] result_list = list(range(len(self.pairwidget_list))) to_insert = [] for ii, src_idx in enumerate(drags_ori): pos = src_idx - ii to_insert.append(result_list.pop(pos)) for ii, tgt_idx in enumerate(drags_tgt): result_list.insert(tgt_idx, to_insert[ii]) drags_ori, drags_tgt = [], [] for ii, idx in enumerate(result_list): if ii != idx: drags_ori.append(idx) drags_tgt.append(ii) self.rearrange_blks.emit((drags_ori, drags_tgt)) return super().mouseMoveEvent(e) Loading @@ -486,12 +600,14 @@ class TextEditListScrollArea(QScrollArea): def clearDrag(self): self.drag_to_pos = -1 if self.drag is not None: try: self.drag.cancel() except RuntimeError: pass self.drag = None def dragMoveEvent(self, e: QDragMoveEvent) -> None: e.accept() e.position() return super().dragMoveEvent(e) def dragEnterEvent(self, e: QDragEnterEvent): Loading @@ -509,6 +625,26 @@ class TextEditListScrollArea(QScrollArea): self.drag_to_pos = to_pos self.set_drag_style(to_pos) def on_idx_edited(self, src_idx: int, tgt_idx: int): src_idx_ori = tgt_idx tgt_idx = max(min(tgt_idx, len(self.pairwidget_list) - 1), 0) if src_idx_ori != tgt_idx: self.pairwidget_list[src_idx].idx_label.setText(str(src_idx + 1).zfill(2)) if src_idx == tgt_idx: return ids_ori, ids_tgt = [src_idx], [tgt_idx] if src_idx < tgt_idx: for idx in range(src_idx+1, tgt_idx+1): ids_ori.append(idx) ids_tgt.append(idx-1) else: for idx in range(tgt_idx, src_idx): ids_ori.append(idx) ids_tgt.append(idx+1) self.rearrange_blks.emit((ids_ori, ids_tgt, (tgt_idx, src_idx))) # self.ensureVisible def addPairWidget(self, pairwidget: TransPairWidget): self.vlayout.insertWidget(pairwidget.idx, pairwidget) pairwidget.check_state_changed.connect(self.on_widget_checkstate_changed) Loading Loading @@ -612,7 +748,6 @@ class TextEditListScrollArea(QScrollArea): if idx == 0: self.sel_anchor_widget = pw def clearAllSelected(self, emit_signal=True): self.sel_anchor_widget = None if len(self.checked_list) > 0: Loading Loading
ui/drawingpanel.py +1 −1 Original line number Diff line number Diff line Loading @@ -338,7 +338,7 @@ class DrawingPanel(Widget): self.setPenToolColor([0, 0, 0, 127]) self.toolConfigStackwidget = QStackedWidget() self.toolConfigStackwidget.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) self.toolConfigStackwidget.setSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Minimum) self.toolConfigStackwidget.addWidget(self.inpaintConfigPanel) self.toolConfigStackwidget.addWidget(self.penConfigPanel) self.toolConfigStackwidget.addWidget(self.rectPanel) Loading
ui/fontformatpanel.py +3 −4 Original line number Diff line number Diff line Loading @@ -425,7 +425,7 @@ class TextStyleLabel(Widget): self.active_stylename_edited = active_stylename_edited self.stylelabel = StyleLabel(style_name, parent=self) self.stylelabel.edit_finished.connect(self.on_style_name_edited) self.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) self.setSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Maximum) self.setToolTip(self.tr('Click to set as Global format. Double click to edit name.')) self.setCursor(Qt.CursorShape.PointingHandCursor) Loading Loading @@ -642,8 +642,7 @@ class TextStyleArea(QScrollArea): self.flayout.addWidget(self.new_btn) self.flayout.addWidget(self.clear_btn) # self.scrollContent.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) self.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Maximum) ScrollBar(Qt.Orientation.Vertical, self) self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) Loading Loading @@ -880,7 +879,7 @@ class TextStylePanel(Widget): self.style_area.hide() self.title_label.clicked.connect(self.on_title_label_clicked) self.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum) self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Maximum) def expand(self): if not self.title_label.expanded: Loading
ui/scenetext_manager.py +42 −13 Original line number Diff line number Diff line Loading @@ -248,32 +248,56 @@ class RearrangeBlksCommand(QUndoCommand): def __init__(self, rmap: Tuple, ctrl, parent=None): super().__init__(parent) self.ctrl: SceneTextManager = ctrl self.src_ids, self.tgt_ids = rmap self.src_ids, self.tgt_ids = rmap[0], rmap[1] self.nr = len(self.src_ids) self.src2tgt = {} self.tgt2src = {} for s, t in zip(self.src_ids, self.tgt_ids): self.src2tgt[s] = t self.tgt2src[t] = s self.visible_ = None self.redo_visible_idx = self.undo_visible_idx = None if len(rmap) > 2: self.redo_visible_idx, self.undo_visible_idx = rmap[2] def redo(self): self.rearrage_blk_ids(self.src_ids, self.tgt_ids) self.rearange_blk_ids(self.src_ids, self.tgt_ids, self.redo_visible_idx) def undo(self): self.rearrage_blk_ids(self.tgt_ids, self.src_ids) self.rearange_blk_ids(self.tgt_ids, self.src_ids, self.undo_visible_idx) def rearange_blk_ids(self, src_ids, tgt_ids, visible_idx = None): src_ids = np.array(src_ids) tgt_ids = np.array(tgt_ids) src_order_ids = np.argsort(src_ids)[::-1] src_ids = src_ids[src_order_ids] tgt_ids = tgt_ids[src_order_ids] def rearrage_blk_ids(self, src_ids, tgt_ids): blks: List[TextBlkItem] = [] pws: List[TransPairWidget] = [] for ii, src_idx in enumerate(src_ids): pos = src_idx - ii for pos, pos_tgt in zip(src_ids, tgt_ids): pw = self.ctrl.pairwidget_list.pop(pos) self.ctrl.textEditList.removeWidget(pw, remove_checked=False) if visible_idx == pos_tgt: pw.hide() blk = self.ctrl.textblk_item_list.pop(pos) pws.append(pw) blks.append(blk) for ii, tgt_idx in enumerate(tgt_ids): self.ctrl.textblk_item_list.insert(tgt_idx, blks[ii]) self.ctrl.pairwidget_list.insert(tgt_idx, pws[ii]) self.ctrl.textEditList.insertPairWidget(pws[ii], tgt_idx) tgt_order_ids = np.argsort(tgt_ids) for ii in tgt_order_ids: pos = tgt_ids[ii] self.ctrl.textblk_item_list.insert(pos, blks[ii]) self.ctrl.textEditList.insertPairWidget(pws[ii], pos) self.ctrl.pairwidget_list.insert(pos, pws[ii]) self.ctrl.updateTextBlkItemIdx() # some optimization could be done here self.ctrl.updateTextBlkItemIdx(set(tgt_ids)) if visible_idx is not None: pw_ct = self.ctrl.pairwidget_list[visible_idx] pw_ct.show() self.ctrl.textEditList.ensureWidgetVisible(pw_ct, yMargin=pw.height()) class TextPanel(Widget): def __init__(self, app: QApplication, *args, **kwargs) -> None: Loading Loading @@ -404,6 +428,7 @@ class SceneTextManager(QObject): pair_widget.e_trans.show_select_menu.connect(self.on_show_select_menu) pair_widget.e_trans.focus_out.connect(self.on_pairw_focusout) pair_widget.drag_move.connect(self.textEditList.handle_drag_pos) pair_widget.idx_edited.connect(self.textEditList.on_idx_edited) self.new_textblk.emit(blk_item.idx) return blk_item Loading Loading @@ -941,6 +966,7 @@ class SceneTextManager(QObject): def on_transwidget_selection_changed(self): selitems = self.canvas.selected_text_items() selset = {pw.idx: pw for pw in self.textEditList.checked_list} self.canvas.block_selection_signal = True for blkitem in selitems: if blkitem.idx not in selset: blkitem.setSelected(False) Loading @@ -948,6 +974,7 @@ class SceneTextManager(QObject): selset.pop(blkitem.idx) for idx in selset: self.textblk_item_list[idx].setSelected(True) self.canvas.block_selection_signal = False def on_textedit_list_focusout(self): fw = self.app.focusWidget() Loading @@ -966,8 +993,10 @@ class SceneTextManager(QObject): if len(selected_blks) > 0: self.canvas.push_undo_command(ApplyEffectCommand(selected_blks, ffmt)) def updateTextBlkItemIdx(self): def updateTextBlkItemIdx(self, sel_ids: set = None): for ii, blk_item in enumerate(self.textblk_item_list): if sel_ids is not None and ii not in sel_ids: continue blk_item.idx = ii self.pairwidget_list[ii].updateIndex(ii) cl = self.textEditList.checked_list Loading
ui/stylewidgets.py +0 −5 Original line number Diff line number Diff line Loading @@ -529,11 +529,6 @@ class ClickableLabel(QLabel): self.clicked.emit() return super().mousePressEvent(e) class IgnoreMouseLabel(QLabel): def mousePressEvent(self, e: QMouseEvent) -> None: e.ignore() return super().mousePressEvent(e) class CheckableLabel(QLabel): Loading
ui/textedit_area.py +145 −10 Original line number Diff line number Diff line from typing import List, Union from qtpy.QtWidgets import QTextEdit, QScrollArea, QGraphicsDropShadowEffect, QVBoxLayout, QApplication, QHBoxLayout, QSizePolicy from qtpy.QtCore import Signal, Qt, QMimeData, QEvent, QPoint from qtpy.QtGui import QColor, QFocusEvent, QInputMethodEvent, QDragEnterEvent, QDragMoveEvent, QDropEvent, QKeyEvent, QTextCursor, QMouseEvent, QDrag, QPixmap, QKeySequence from qtpy.QtWidgets import QStackedWidget, QSizePolicy, QTextEdit, QScrollArea, QGraphicsDropShadowEffect, QVBoxLayout, QApplication, QHBoxLayout, QSizePolicy, QLabel, QLineEdit from qtpy.QtCore import Signal, Qt, QMimeData, QEvent, QPoint, QSize from qtpy.QtGui import QIntValidator, QColor, QFocusEvent, QInputMethodEvent, QDragEnterEvent, QDragMoveEvent, QDropEvent, QKeyEvent, QTextCursor, QMouseEvent, QDrag, QPixmap, QKeySequence import keyboard import webbrowser import numpy as np from .stylewidgets import Widget, SeparatorWidget, ClickableLabel, IgnoreMouseLabel, ScrollBar from .stylewidgets import Widget, SeparatorWidget, ClickableLabel, ScrollBar from .textitem import TextBlock from utils.config import pcfg from utils.logger import logger as LOGGER STYLE_TRANSPAIR_CHECKED = "background-color: rgba(30, 147, 229, 20%);" Loading Loading @@ -304,19 +305,110 @@ class TransTextEdit(SourceTextEdit): pass class RowIndexEditor(QLineEdit): focus_out = Signal() def __init__(self, parent=None): super().__init__(parent=parent) self.setValidator(QIntValidator()) self.setReadOnly(True) self.setTextMargins(0, 0, 0, 0) def focusOutEvent(self, e: QFocusEvent) -> None: super().focusOutEvent(e) self.focus_out.emit() def minimumSizeHint(self): size = super().minimumSizeHint() return QSize(1, size.height()) def sizeHint(self): size = super().sizeHint() return QSize(1, size.height()) class RowIndexLabel(QStackedWidget): submmit_idx = Signal(int) def __init__(self, text: str = None, parent=None): super().__init__(parent=parent) self.lineedit = RowIndexEditor(parent=self) self.lineedit.focus_out.connect(self.on_lineedit_focusout) self.show_label = QLabel(self) self.text = self.show_label.text self.addWidget(self.show_label) self.addWidget(self.lineedit) self.setCurrentIndex(0) if text is not None: self.setText(text) self.setSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Maximum) def setText(self, text): if isinstance(text, int): text = str(text) self.show_label.setText(text) self.lineedit.setText(text) def keyPressEvent(self, e: QKeyEvent) -> None: super().keyPressEvent(e) key = e.key() if key == Qt.Key.Key_Return: self.try_update_idx() def try_update_idx(self): idx_str = self.lineedit.text().strip() if not idx_str: return if self.text() == idx_str: return try: idx = int(idx_str) self.lineedit.setReadOnly(True) self.submmit_idx.emit(idx) except Exception as e: LOGGER.warning(f'Invalid index str: {idx}') def mouseDoubleClickEvent(self, e: QMouseEvent) -> None: self.startEdit() return super().mouseDoubleClickEvent(e) def startEdit(self) -> None: self.setCurrentIndex(1) self.lineedit.setReadOnly(False) self.lineedit.setFocus() def on_lineedit_focusout(self): edited = not self.lineedit.isReadOnly() self.lineedit.setReadOnly(True) self.setCurrentIndex(0) if edited: self.try_update_idx() def mousePressEvent(self, e: QMouseEvent) -> None: e.ignore() return super().mousePressEvent(e) class TransPairWidget(Widget): check_state_changed = Signal(object, bool, bool) drag_move = Signal(int) idx_edited = Signal(int, int) def __init__(self, textblock: TextBlock = None, idx: int = None, fold: bool = False, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.e_source = SourceTextEdit(idx, self, fold) self.e_trans = TransTextEdit(idx, self, fold) self.idx_label = IgnoreMouseLabel(self) self.idx_label = RowIndexLabel(idx, self) self.idx_label.setText(str(idx + 1).zfill(2)) # showed index start from 1! self.submmit_idx = self.idx_label.submmit_idx.connect(self.on_idx_edited) self.textblock = textblock self.idx = idx self.checked = False Loading @@ -339,6 +431,10 @@ class TransPairWidget(Widget): self.setAcceptDrops(True) def on_idx_edited(self, new_idx: int): new_idx -= 1 self.idx_edited.emit(self.idx, new_idx) def dragEnterEvent(self, e: QDragEnterEvent) -> None: if isinstance(e.source(), TransPairWidget): e.accept() Loading Loading @@ -369,7 +465,7 @@ class TransPairWidget(Widget): else: self.setStyleSheet("") def mouseReleaseEvent(self, e: QMouseEvent) -> None: def update_checkstate_by_mousevent(self, e: QMouseEvent): if e.button() == Qt.MouseButton.LeftButton: modifiers = e.modifiers() if modifiers & Qt.KeyboardModifier.ShiftModifier and modifiers & Qt.KeyboardModifier.ControlModifier: Loading @@ -378,7 +474,11 @@ class TransPairWidget(Widget): shift_pressed = modifiers == Qt.KeyboardModifier.ShiftModifier ctrl_pressed = modifiers == Qt.KeyboardModifier.ControlModifier self.check_state_changed.emit(self, shift_pressed, ctrl_pressed) return super().mouseReleaseEvent(e) def mousePressEvent(self, e: QMouseEvent) -> None: if not self.checked: self.update_checkstate_by_mousevent(e) return super().mousePressEvent(e) def updateIndex(self, idx: int): if self.idx != idx: Loading Loading @@ -464,7 +564,21 @@ class TextEditListScrollArea(QScrollArea): new_maps = np.where(drags != new_pos) if len(new_maps) == 0: return drags_ori, drags_tgt = drags[new_maps], new_pos[new_maps] result_list = list(range(len(self.pairwidget_list))) to_insert = [] for ii, src_idx in enumerate(drags_ori): pos = src_idx - ii to_insert.append(result_list.pop(pos)) for ii, tgt_idx in enumerate(drags_tgt): result_list.insert(tgt_idx, to_insert[ii]) drags_ori, drags_tgt = [], [] for ii, idx in enumerate(result_list): if ii != idx: drags_ori.append(idx) drags_tgt.append(ii) self.rearrange_blks.emit((drags_ori, drags_tgt)) return super().mouseMoveEvent(e) Loading @@ -486,12 +600,14 @@ class TextEditListScrollArea(QScrollArea): def clearDrag(self): self.drag_to_pos = -1 if self.drag is not None: try: self.drag.cancel() except RuntimeError: pass self.drag = None def dragMoveEvent(self, e: QDragMoveEvent) -> None: e.accept() e.position() return super().dragMoveEvent(e) def dragEnterEvent(self, e: QDragEnterEvent): Loading @@ -509,6 +625,26 @@ class TextEditListScrollArea(QScrollArea): self.drag_to_pos = to_pos self.set_drag_style(to_pos) def on_idx_edited(self, src_idx: int, tgt_idx: int): src_idx_ori = tgt_idx tgt_idx = max(min(tgt_idx, len(self.pairwidget_list) - 1), 0) if src_idx_ori != tgt_idx: self.pairwidget_list[src_idx].idx_label.setText(str(src_idx + 1).zfill(2)) if src_idx == tgt_idx: return ids_ori, ids_tgt = [src_idx], [tgt_idx] if src_idx < tgt_idx: for idx in range(src_idx+1, tgt_idx+1): ids_ori.append(idx) ids_tgt.append(idx-1) else: for idx in range(tgt_idx, src_idx): ids_ori.append(idx) ids_tgt.append(idx+1) self.rearrange_blks.emit((ids_ori, ids_tgt, (tgt_idx, src_idx))) # self.ensureVisible def addPairWidget(self, pairwidget: TransPairWidget): self.vlayout.insertWidget(pairwidget.idx, pairwidget) pairwidget.check_state_changed.connect(self.on_widget_checkstate_changed) Loading Loading @@ -612,7 +748,6 @@ class TextEditListScrollArea(QScrollArea): if idx == 0: self.sel_anchor_widget = pw def clearAllSelected(self, emit_signal=True): self.sel_anchor_widget = None if len(self.checked_list) > 0: Loading