Commit e1499632 authored by dmMaze's avatar dmMaze
Browse files

sync search results with editing

parent 63e4b78d
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ class SourceTextEdit(QTextEdit):
    hover_leave = Signal(int)
    focus_in = Signal(int)
    user_edited = Signal()
    ensure_visible = Signal()
    def __init__(self, idx, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.idx = idx
@@ -57,6 +58,7 @@ class SourceTextEdit(QTextEdit):
    def focusInEvent(self, event: QFocusEvent) -> None:
        self.setHoverEffect(True)
        self.focus_in.emit(self.idx)
        self.pre_editing = False
        return super().focusInEvent(event)

    def focusOutEvent(self, event: QFocusEvent) -> None:
@@ -71,15 +73,14 @@ class SourceTextEdit(QTextEdit):
        return super().inputMethodEvent(e)
        
class TransTextEdit(SourceTextEdit):
    content_change = Signal(int, str)
    content_change = Signal(int)
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.document().contentsChange.connect(self.onContentChange)

    def onContentChange(self, pos: int, delete: int, add: int):
        if self.hasFocus():
            text = self.toPlainText()
            self.content_change.emit(self.idx, text)
            self.content_change.emit(self.idx)

class TransPairWidget(Widget):
    def __init__(self, textblock: TextBlock = None, idx: int = None, *args, **kwargs) -> None:
@@ -116,16 +117,19 @@ class TextEditListScrollArea(QScrollArea):
        self.setWidgetResizable(True)
        self.vlayout = vlayout
        
        
    def addPairWidget(self, pairwidget):
        
    def addPairWidget(self, pairwidget: TransPairWidget):
        self.vlayout.addWidget(pairwidget)
        pairwidget.setVisible(True)
        pairwidget.e_trans.ensure_visible.connect(self.on_ensure_visible)
        pairwidget.e_source.ensure_visible.connect(self.on_ensure_visible)

    def removeWidget(self, widget: TransPairWidget):
        widget.setVisible(False)
        self.vlayout.removeWidget(widget)

    def on_ensure_visible(self):
        self.ensureWidgetVisible(self.sender())


class TextPanel(Widget):
    def __init__(self, app: QApplication, *args, **kwargs) -> None:
+1 −0
Original line number Diff line number Diff line
@@ -130,6 +130,7 @@ class MainWindow(QMainWindow):
        self.presetPanel.hide_signal.connect(self.save_config)
        self.presetPanel.load_preset.connect(self.textPanel.formatpanel.on_load_preset)
        self.st_manager = SceneTextManager(self.app, self.canvas, self.textPanel)
        self.st_manager.new_textblk.connect(self.canvas.search_widget.on_new_textblk)
        self.canvas.search_widget.pairwidget_list = self.st_manager.pairwidget_list
        self.canvas.search_widget.textblk_item_list = self.st_manager.textblk_item_list

+5 −4
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@ from typing import List, Union, Tuple
import numpy as np

from qtpy.QtWidgets import QApplication
from qtpy.QtCore import QObject, QRectF, Qt
from qtpy.QtCore import QObject, QRectF, Qt, Signal
from qtpy.QtGui import QTextCursor, QFontMetrics, QFont, QTextCharFormat
try:
    from qtpy.QtWidgets import QUndoCommand
@@ -246,6 +246,7 @@ class AutoLayoutCommand(QUndoCommand):


class SceneTextManager(QObject):
    new_textblk = Signal(int)
    def __init__(self, 
                 app: QApplication,
                 canvas: Canvas, 
@@ -293,7 +294,6 @@ class SceneTextManager(QObject):
                blk_item.hide()

    def adjustSceneTextRect(self):
        new_size = self.canvas.imgLayer.sceneBoundingRect().size()
        self.txtblkShapeControl.updateBoundingRect()

    def clearSceneTextitems(self):
@@ -340,6 +340,7 @@ class SceneTextManager(QObject):
        pair_widget.e_trans.setPlainText(blk_item.toPlainText())
        pair_widget.e_trans.focus_in.connect(self.onTransWidgetHoverEnter)
        pair_widget.e_trans.content_change.connect(self.onTransWidgetContentchange)
        self.new_textblk.emit(blk_item.idx)
        return blk_item

    def addTextBlkItem(self, textblk_item: TextBlkItem) -> TextBlkItem:
@@ -699,10 +700,10 @@ class SceneTextManager(QObject):
        self.canvas.gv.ensureVisible(blk_item)
        self.txtblkShapeControl.setBlkItem(blk_item)

    def onTransWidgetContentchange(self, idx: int, text: str):
    def onTransWidgetContentchange(self, idx: int):
        blk_item = self.textblk_item_list[idx]
        blk_item.setTextInteractionFlags(Qt.NoTextInteraction)
        blk_item.setPlainText(text)
        blk_item.setPlainText(self.pairwidget_list[idx].e_trans.toPlainText())
        self.canvas.setProjSaveState(True)

    def onGlobalFormatChanged(self):
+82 −18
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ class SearchWidget(Widget):
    def __init__(self, parent: QWidget = None, is_floating=True, *args, **kwargs) -> None:
        super().__init__(parent, *args, **kwargs)
        self.is_floating = is_floating
        self.search_rstedit_list: List[QTextEdit] = []
        self.search_rstedit_list: List[SourceTextEdit] = []
        self.search_counter_list: List[int] = []
        self.search_cursorpos_map: List[Dict] = []
        self.counter_sum = 0
@@ -138,8 +138,10 @@ class SearchWidget(Widget):
        self.replace_editor.setPlaceholderText(self.tr('Replace'))
        self.replace_btn = ClickableLabel(None, self)
        self.replace_btn.setObjectName(self.tr('ReplaceBtn'))
        self.replace_btn.clicked.connect(self.on_replace_btn_clicked)
        self.replace_all_btn = ClickableLabel(None, self)
        self.replace_all_btn.setObjectName(self.tr('ReplaceAllBtn'))
        self.replace_all_btn.clicked.connect(self.on_replaceall_btn_clicked)

        hlayout_bar1_0 = QHBoxLayout()
        hlayout_bar1_0.addWidget(self.search_editor)
@@ -288,7 +290,8 @@ class SearchWidget(Widget):
            elif before_current:
                self.result_pos += delta_count
        else:
            self.search_rstedit_list.pop(idx)
            edit = self.search_rstedit_list.pop(idx)
            edit.textChanged.disconnect(self.on_rst_text_changed)
            self.search_cursorpos_map.pop(idx)
            if len(self.search_rstedit_list) == 0:
                self.clearSearchResult()
@@ -353,7 +356,7 @@ class SearchWidget(Widget):
            find_flag |= QTextDocument.FindFlag.FindWholeWords
        return find_flag

    def _find_page_text(self, text_edit: QTextEdit, text: str, find_flag: QTextDocument.FindFlag) -> Tuple[int, Dict]:
    def _find_page_text(self, text_edit: QTextEdit, text: str, find_flag: QTextDocument.FindFlag, highlight=True) -> Tuple[int, Dict]:
        text_edit.blockSignals(True)
        doc = text_edit.document()
        text_cursor = text_edit.textCursor()
@@ -361,14 +364,13 @@ class SearchWidget(Widget):
        cursor = QTextCursor(doc)
        found_counter = 0
        pos_map = {}
        find_pos = 0
        while True:
            cursor: QTextCursor = doc.find(text, find_pos, options=find_flag)
            cursor: QTextCursor = doc.find(text, cursor, options=find_flag)
            if cursor.isNull():
                break
            find_pos = cursor.position() - len(text) + 1
            pos_map[cursor.position()] = found_counter
            found_counter += 1
            if highlight:
                cf = cursor.charFormat()
                cf.setBackground(HIGHLIGHT_COLOR)
                cursor.mergeCharFormat(cf)
@@ -409,7 +411,8 @@ class SearchWidget(Widget):
        if self.current_edit is not None:
            self.updateCurrentCursor()
            idx = self.current_edit_index()
            self.result_pos = self.search_cursorpos_map[idx][self.current_cursor.position()]
            pos_map = self.search_cursorpos_map[idx]
            self.result_pos = pos_map[self.current_cursor.position()]
            if idx > 0:
                self.result_pos += sum(self.search_counter_list[ :idx])
        else:
@@ -436,6 +439,19 @@ class SearchWidget(Widget):
        else:
            sel_start = cursor.selectionStart()
            cursor: QTextCursor = doc.find(text, sel_start, options=find_flag)

        idx = self.current_edit_index()
        pos_map = self.search_cursorpos_map[idx]
        c_pos = cursor.position()
        if c_pos not in pos_map:
            find_flag |= QTextDocument.FindFlag.FindBackward
            for k, val in reversed(pos_map.items()):
                if k < c_pos:
                    text = self.search_editor.toPlainText()
                    cursor.setPosition(k-len(text))
                    cursor.setPosition(k, QTextCursor.MoveMode.KeepAnchor)
                    break

        self.current_cursor = cursor

    def updateCounterText(self):
@@ -451,12 +467,15 @@ class SearchWidget(Widget):
        text = self.search_editor.toPlainText()

        find_flag = self.get_find_flag()
        len_text = len(text)
        if step < 0:
            find_flag |= QTextDocument.FindFlag.FindBackward
            new_cursor: QTextCursor = doc.find(text, self.current_cursor, find_flag)
            new_cursor = self.current_cursor
            while not new_cursor.isNull() and \
                self.current_cursor.position() - new_cursor.position() < len_text:
                new_cursor = doc.find(text, new_cursor, find_flag)
        else:
            find_pos = self.current_cursor.position() - len(text) + 1
            new_cursor: QTextCursor = doc.find(text, find_pos, find_flag)
            new_cursor: QTextCursor = doc.find(text, self.current_cursor, find_flag)
        if new_cursor.isNull():
            idx = self.current_edit_index() + step
            if idx >= len(self.search_rstedit_list) or idx < 0:
@@ -479,14 +498,18 @@ class SearchWidget(Widget):
        if self.current_edit is None or not self.current_cursor.hasSelection():
            return
        self.current_edit.blockSignals(True)
        text_cursor = self.current_edit.textCursor()
        if text_cursor.hasSelection():
            text_cursor.clearSelection()
            self.current_edit.setTextCursor(text_cursor)
        cursor = self.current_edit.textCursor()
        if cursor.hasSelection():
            cursor.clearSelection()
        cursor.setPosition(self.current_cursor.position())
        self.current_edit.setTextCursor(cursor)
        
        cf = self.current_cursor.charFormat()
        cf.setBackground(CURRENT_TEXT_COLOR)
        self.current_cursor.setCharFormat(cf)
        self.current_edit.blockSignals(False)
        self.current_edit.setFocus()
        self.current_edit.ensure_visible.emit()

    def on_next_search_result(self):
        if self.current_cursor is None:
@@ -525,4 +548,45 @@ class SearchWidget(Widget):
    def on_commit_search(self):
        self.page_search()

    def on_replaceall_btn_clicked(self):
        pass

    def on_replace_btn_clicked(self):
        pass

    def on_new_textblk(self, idx: int):
        if self.isVisible():
            pair_widget = self.pairwidget_list[idx]
            pair_widget.e_trans.textChanged.connect(self.on_nonrst_edit_text_changed)
            pair_widget.e_source.textChanged.connect(self.on_nonrst_edit_text_changed)

    def on_nonrst_edit_text_changed(self):
        edit: SourceTextEdit = self.sender()
        if not self.isVisible() or edit.pre_editing or edit in self.search_rstedit_list:
            return

        if type(edit) == SourceTextEdit and self.range_combobox.currentIndex() == 0 \
            or type(edit) == TransPairWidget and self.range_combobox.currentIndex() == 1:
            return
        
        text = self.search_editor.toPlainText()
        find_flag = self.get_find_flag()
        found_counter, pos_map = self._find_page_text(edit, text, find_flag)
        if found_counter > 0:
            current_idx = self.current_edit_index()
            insert_idx = 0
            for e in self.search_rstedit_list:
                if e.idx < edit.idx:
                    insert_idx += 1
                elif e.idx == edit.idx:
                    if type(edit) == TransTextEdit:
                        insert_idx += 1
            if current_idx >= insert_idx:
                self.result_pos += found_counter
            self.search_cursorpos_map.insert(insert_idx, pos_map)
            edit.textChanged.connect(self.on_rst_text_changed)
            self.search_counter_list.insert(insert_idx, found_counter)
            self.search_rstedit_list.insert(insert_idx, edit)
            self.counter_sum += found_counter
            
            self.updateCounterText()
+11 −2
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ from typing import List, Union, Tuple

from qtpy.QtWidgets import QGraphicsItem, QWidget, QGraphicsSceneHoverEvent, QGraphicsTextItem, QStyleOptionGraphicsItem, QStyle, QGraphicsSceneMouseEvent
from qtpy.QtCore import Qt, QRect, QRectF, QPointF, Signal, QSizeF
from qtpy.QtGui import QKeyEvent, QFont, QTextCursor, QPixmap, QPainterPath, QTextDocument, QFocusEvent, QPainter, QPen, QColor, QTextCursor, QTextCharFormat, QTextDocument
from qtpy.QtGui import QKeyEvent, QFont, QTextCursor, QPixmap, QPainterPath, QTextDocument, QInputMethodEvent, QPainter, QPen, QColor, QTextCursor, QTextCharFormat, QTextDocument

from dl.textdetector.textblock import TextBlock
from utils.imgproc_utils import xywh2xyxypoly, rotate_polygons
@@ -31,6 +31,7 @@ class TextBlkItem(QGraphicsTextItem):
    pasted = Signal(int)
    def __init__(self, blk: TextBlock = None, idx: int = 0, set_format=True, show_rect=False, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pre_editing = False
        self.blk = None
        self.repainting = False
        self.reshaping = False
@@ -62,11 +63,18 @@ class TextBlkItem(QGraphicsTextItem):
        self.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable)
        self.setCacheMode(QGraphicsItem.CacheMode.DeviceCoordinateCache)

    def inputMethodEvent(self, e: QInputMethodEvent):
        if e.preeditString() == '':
            self.pre_editing = False
        else:
            self.pre_editing = True
        super().inputMethodEvent(e)
        
    def is_editting(self):
        return self.textInteractionFlags() == Qt.TextInteractionFlag.TextEditorInteraction

    def onDocumentContentChanged(self):
        if self.hasFocus():   
        if self.hasFocus() and not self.pre_editing:   
            self.content_changed.emit(self)
        if self.repaint_on_changed:
            if not self.repainting:
@@ -410,6 +418,7 @@ class TextBlkItem(QGraphicsTextItem):
        super().paint(painter, option, widget)

    def startEdit(self) -> None:
        self.pre_editing = False
        self.setCacheMode(QGraphicsItem.CacheMode.NoCache)
        self.setTextInteractionFlags(Qt.TextEditorInteraction)
        self.setFocus()