Skip to content

Commit

Permalink
Editable line number, close #439
Browse files Browse the repository at this point in the history
  • Loading branch information
dmMaze committed Jun 28, 2024
1 parent 319c0d4 commit 5669988
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 33 deletions.
2 changes: 1 addition & 1 deletion ui/drawingpanel.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ def __init__(self, canvas: Canvas, inpainter_panel: InpaintConfigPanel, *args, *
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)
Expand Down
7 changes: 3 additions & 4 deletions ui/fontformatpanel.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ def __init__(self, style_name: str = '', parent: Widget = None, fontfmt: FontFor
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)
Expand Down Expand Up @@ -642,8 +642,7 @@ def __init__(self, parent: Widget = None):
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)
Expand Down Expand Up @@ -880,7 +879,7 @@ def __init__(self, text=None, parent=None, expanded=True, *args, **kwargs):
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:
Expand Down
55 changes: 42 additions & 13 deletions ui/scenetext_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]

def rearrage_blk_ids(self, src_ids, tgt_ids):
src_ids = src_ids[src_order_ids]
tgt_ids = tgt_ids[src_order_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:
Expand Down Expand Up @@ -404,6 +428,7 @@ def addTextBlock(self, blk: Union[TextBlock, TextBlkItem] = None) -> TextBlkItem
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
Expand Down Expand Up @@ -941,13 +966,15 @@ def apply_fontformat(self, fontformat: FontFormat):
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)
else:
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()
Expand All @@ -966,8 +993,10 @@ def on_apply_effect(self):
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
Expand Down
5 changes: 0 additions & 5 deletions ui/stylewidgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,12 +528,7 @@ def mousePressEvent(self, e: QMouseEvent) -> None:
if e.button() == Qt.MouseButton.LeftButton:
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):

Expand Down
155 changes: 145 additions & 10 deletions ui/textedit_area.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
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%);"
Expand Down Expand Up @@ -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
Expand All @@ -339,6 +431,10 @@ def __init__(self, textblock: TextBlock = None, idx: int = None, fold: bool = Fa

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()
Expand Down Expand Up @@ -369,7 +465,7 @@ def _set_checked_state(self, checked: bool):
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:
Expand All @@ -378,7 +474,11 @@ def mouseReleaseEvent(self, e: QMouseEvent) -> None:
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:
Expand Down Expand Up @@ -464,7 +564,21 @@ def mouseMoveEvent(self, e: QMouseEvent) -> None:
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)
Expand All @@ -486,12 +600,14 @@ def set_drag_style(self, pos: int, clear_style: bool = False):
def clearDrag(self):
self.drag_to_pos = -1
if self.drag is not None:
self.drag.cancel()
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):
Expand All @@ -508,7 +624,27 @@ def handle_drag_pos(self, to_pos: int):
self.set_drag_style(self.drag_to_pos, True)
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)
Expand Down Expand Up @@ -612,7 +748,6 @@ def set_selected_list(self, selection_indices: List):
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:
Expand Down

0 comments on commit 5669988

Please sign in to comment.