Skip to content

Commit

Permalink
Merge branch 'dmMaze:dev' into paddle_ocr
Browse files Browse the repository at this point in the history
  • Loading branch information
bropines authored Oct 31, 2024
2 parents 49ffb88 + a4c5034 commit 042486b
Show file tree
Hide file tree
Showing 12 changed files with 188 additions and 30 deletions.
19 changes: 18 additions & 1 deletion config/stylesheet.css
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,14 @@ QMenu::item:selected {
}

QDialog {
font-size: 7px;
font-size: 14px;
background-color: @widgetBackgroundColor;
}

QDialog QPushButton {
padding: 5px 15px;
}

QGroupBox {
background-color: @emptyContentBackgroundColor;
}
Expand Down Expand Up @@ -1002,6 +1006,19 @@ TextStyleLabel {
border-radius: 7px;
}

SmallParamLabel {
font-size: 12px;
height: 20px;
}

SmallComboBox {
height: 20px;
font-size: 12px;
/* padding-left: 8px; */
border: 1px solid @borderColor;
background-color: @transtexteditBackgroundColor;
}

ArrowLeftButton {
image: url(icons/arrow-left.svg);
border: none;
Expand Down
6 changes: 6 additions & 0 deletions translate/zh_CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,12 @@
<source>Failed to load project from</source>
<translation>无法从所选路径加载项目:</translation>
</message>
<message>
<location filename="../ui/mainwindow.py" line="1081"/>
<source>Are you sure to run image translation again?
All existing translation results will be cleared!</source>
<translation>确定要重新运行吗?现有翻译结果将被清空!</translation>
</message>
</context>
<context>
<name>ModuleManager</name>
Expand Down
71 changes: 71 additions & 0 deletions ui/config_proj.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,39 @@ def read_jpg_metadata(imgpath: str):
bubdict = json.loads(user_comment)
return bubdict

page_start_pattern = re.compile(r'^###\s+', re.MULTILINE)
text_blkid_start_pattern = re.compile(r'^\d+\.', re.MULTILINE)

def parse_txt_translation(file_path: str):
with open(file_path, 'r', encoding='utf8') as f:
content = f.read()
page_start = None
page_list = []
for matched in page_start_pattern.finditer(content):
start, end = matched.span()
if page_start is not None:
page_list.append({'page_content': content[page_start: start]})
page_start = start
if page_start is not None:
page_list.append({'page_content': content[page_start:]})

for page_dict in page_list:
page_content = page_dict['page_content']
page_dict['page_name'] = page_start_pattern.sub('', page_content.split('\n')[0]).strip()
blkid_start = blkid_end = None
blk_list = []
for matched in text_blkid_start_pattern.finditer(page_content):
start, end = matched.span()
if blkid_start is not None:
blk_list.append(page_content[blkid_end: start].strip())
blkid_start = start
blkid_end = end
if blkid_start is not None:
blk_list.append(page_content[blkid_end:])
page_dict['blk_list'] = blk_list

return page_list


class TextBlkEncoder(NumpyEncoder):
def default(self, obj):
Expand Down Expand Up @@ -139,6 +172,40 @@ def load_from_dict(self, proj_dict: dict):
if len(self.pages) > 0:
self.set_current_img_byidx(0)

def load_translation_from_txt(self, file_path: str):
page_list = parse_txt_translation(file_path)
missing_pages = []
unmatched_pages = []
unexpected_pages = []
matched_pages = []
for page_dict in page_list:
page_name = page_dict['page_name']
if page_name in self.pages:
matched_pages.append(page_name)
else:
unexpected_pages.append(page_name)
continue
blklist = self.pages[page_name]
n_blk = len(blklist)
src_blk_list = page_dict['blk_list']
n_src_blk = len(src_blk_list)
if n_src_blk != n_blk:
LOGGER.warning(f'Unmatched text blocks in {page_name}, number of text blocks in this page vs source file: {n_blk}-{n_src_blk}')
unmatched_pages.append(page_name)
for blkid in range(min(n_blk, n_src_blk)):
blk = blklist[blkid]
blk.rich_text = ''
blk.translation = src_blk_list[blkid]

matched_pages = set(matched_pages)
if len(matched_pages) != self.num_pages:
for page_name in self.pages:
if page_name not in matched_pages:
missing_pages.append(page_name)

all_matched = len(missing_pages) == 0 and len(unmatched_pages) == 0 and len(unexpected_pages) == 0
return all_matched, {'missing_pages': missing_pages, 'unmatched_pages': unmatched_pages, 'unexpected_pages': unexpected_pages, 'matched_pages': matched_pages}

def load_from_json(self, json_path: str):
old_dir = self.directory
directory = osp.dirname(json_path)
Expand Down Expand Up @@ -306,6 +373,10 @@ def backup(self):
def is_empty(self):
return len(self.pages) == 0

@property
def is_all_pages_no_text(self):
return all([len(blklist) == 0 for blklist in self.pages.values()])

@property
def img_valid(self):
return self.img_array is not None
Expand Down
4 changes: 2 additions & 2 deletions ui/custom_widget/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from .scrollbar import ScrollBar
from .combobox import ComboBox, ConfigComboBox, ParamComboBox, SizeComboBox
from .combobox import ComboBox, ConfigComboBox, ParamComboBox, SizeComboBox, SmallComboBox
from .widget import Widget, SeparatorWidget
from .view_panel import PanelGroupBox, PanelArea, PanelAreaContent, ViewWidget, ExpandLabel
from .message import MessageBox, TaskProgressBar, FrameLessMessageBox, ProgressMessageBox, ImgtransProgressMessageBox
from .flow_layout import FlowLayout
from .label import FadeLabel, ColorPickerLabel, ClickableLabel, CheckableLabel, TextCheckerLabel
from .label import FadeLabel, ColorPickerLabel, ClickableLabel, CheckableLabel, TextCheckerLabel, ParamNameLabel, SmallParamLabel
from .slider import PaintQSlider
from .helper import isDarkTheme, themeColor
from .push_button import NoBorderPushBtn
Expand Down
4 changes: 4 additions & 0 deletions ui/custom_widget/combobox.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ def wheelEvent(self, *args, **kwargs):
return super().wheelEvent(*args, **kwargs)
else:
return self.scrollWidget.wheelEvent(*args, **kwargs)


class SmallComboBox(ComboBox):
pass


class ConfigComboBox(ComboBox):
Expand Down
31 changes: 31 additions & 0 deletions ui/custom_widget/label.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from qtpy.QtGui import QMouseEvent, QWheelEvent, QColor


from utils.shared import CONFIG_FONTSIZE_CONTENT

class FadeLabel(QLabel):
def __init__(self, *args, **kwargs):
Expand Down Expand Up @@ -141,3 +142,33 @@ def mousePressEvent(self, event: QMouseEvent):
self.checkStateChanged.emit(self.checked)


class ParamNameLabel(QLabel):
def __init__(self, param_name: str, alignment = None, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)

if alignment is None:
self.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
else:
self.setAlignment(alignment)

font = self.font()
font.setPointSizeF(CONFIG_FONTSIZE_CONTENT-2)
self.setFont(font)
self.setText(param_name)
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground, True)


class SmallParamLabel(QLabel):
def __init__(self, param_name: str, alignment = None, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)

if alignment is None:
self.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
else:
self.setAlignment(alignment)

# font = self.font()
# font.setPointSizeF(CONFIG_FONTSIZE_CONTENT-2)
# self.setFont(font)
self.setText(param_name)
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground, True)
52 changes: 46 additions & 6 deletions ui/mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from utils.text_processing import is_cjk, full_len, half_len
from utils.textblock import TextBlock, TextAlignment
from utils import shared
from utils import create_error_dialog
from utils import create_error_dialog, create_info_dialog
from modules.translators.trans_chatgpt import GPTTranslator
from .misc import parse_stylesheet, set_html_family, QKEY
from utils.config import ProgramConfig, pcfg, save_config, text_styles, save_text_styles, load_textstyle_from, FontFormat
Expand Down Expand Up @@ -139,6 +139,7 @@ def setupUi(self):
self.leftBar.export_trans_txt.connect(lambda : self.on_export_txt(dump_target='translation'))
self.leftBar.export_src_md.connect(lambda : self.on_export_txt(dump_target='source', suffix='.md'))
self.leftBar.export_trans_md.connect(lambda : self.on_export_txt(dump_target='translation', suffix='.md'))
self.leftBar.import_trans_txt.connect(self.on_import_trans_txt)

self.pageList = PageListView()
self.pageList.reveal_file.connect(self.on_reveal_file)
Expand Down Expand Up @@ -278,7 +279,7 @@ def setupConfig(self):
module_manager.blktrans_pipeline_finished.connect(self.on_blktrans_finished)
module_manager.imgtrans_thread.post_process_mask = self.drawingPanel.rectPanel.post_process_mask

self.leftBar.run_imgtrans.connect(self.on_run_imgtrans)
self.leftBar.run_imgtrans_clicked.connect(self.run_imgtrans)
self.bottomBar.inpaint_btn_clicked.connect(self.inpaintBtnClicked)
self.bottomBar.translatorStatusbtn.clicked.connect(self.translatorStatusBtnPressed)
self.bottomBar.transTranspageBtn.run_target.connect(self.on_transpagebtn_pressed)
Expand Down Expand Up @@ -476,7 +477,6 @@ def pageListCurrentItemChanged(self):
self.imgtrans_proj.set_current_img(item.text())
self.canvas.clear_undostack(update_saved_step=True)
self.canvas.updateCanvas()
self.st_manager.hovering_transwidget = None
self.st_manager.updateSceneTextitems()
self.titleBar.setTitleContent(page_name=self.imgtrans_proj.current_img)
self.module_manager.handle_page_changed()
Expand Down Expand Up @@ -1077,11 +1077,17 @@ def on_display_lang_changed(self, lang: str):
self.set_display_lang(lang)

def run_imgtrans(self):
if not self.imgtrans_proj.is_all_pages_no_text:
reply = QMessageBox.question(self, self.tr('Confirmation'),
self.tr('Are you sure to run image translation again?\nAll existing translation results will be cleared!'),
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply != QMessageBox.Yes:
return
self.on_run_imgtrans()

def run_imgtrans_wo_textstyle_update(self):
self._run_imgtrans_wo_textstyle_update = True
self.on_run_imgtrans()
self.run_imgtrans()

def on_run_imgtrans(self):
self.backup_blkstyles.clear()
Expand Down Expand Up @@ -1180,7 +1186,41 @@ def on_export_txt(self, dump_target, suffix='.txt'):
msg.setText(self.tr('Text file exported to ') + self.imgtrans_proj.dump_txt_path(dump_target, suffix))
msg.exec_()
except Exception as e:
create_error_dialog(e, self.tr('failed to export as TEXT file'))
create_error_dialog(e, self.tr('Failed to export as TEXT file'))

def on_import_trans_txt(self):
try:
selected_file = ''
dialog = QFileDialog()
selected_file = str(dialog.getOpenFileUrl(self.parent(), self.tr('Import *.md/*.txt'), filter="*.txt *.md *.TXT *.MD")[0].toLocalFile())
if not osp.exists(selected_file):
return

all_matched, match_rst = self.imgtrans_proj.load_translation_from_txt(selected_file)
matched_pages = match_rst['matched_pages']

if self.imgtrans_proj.current_img in matched_pages:
self.canvas.clear_undostack(update_saved_step=True)
self.st_manager.updateSceneTextitems()

if all_matched:
msg = self.tr('Translation imported and matched successfully.')
else:
msg = self.tr('Imported txt file not fully matched with current project, please make sure source txt file structured like results from \"export TXT/markdown\"')
if len(match_rst['missing_pages']) > 0:
msg += '\n' + self.tr('Missing pages: ') + '\n'
msg += '\n'.join(match_rst['missing_pages'])
if len(match_rst['unexpected_pages']) > 0:
msg += '\n' + self.tr('Unexpected pages: ') + '\n'
msg += '\n'.join(match_rst['unexpected_pages'])
if len(match_rst['unmatched_pages']) > 0:
msg += '\n' + self.tr('Unmatched pages: ') + '\n'
msg += '\n'.join(match_rst['unmatched_pages'])
msg = msg.strip()
create_info_dialog(msg)

except Exception as e:
create_error_dialog(e, self.tr('Failed to import translation from ') + selected_file)

def on_reveal_file(self):
current_img_path = self.imgtrans_proj.current_img_path()
Expand Down Expand Up @@ -1321,7 +1361,7 @@ def run_next_dir(self):
shared.pbar['translate'] = tqdm(range(npages), desc="Translation")
if pcfg.module.enable_inpaint:
shared.pbar['inpaint'] = tqdm(range(npages), desc="Inpaint")
self.run_imgtrans()
self.on_run_imgtrans()

def on_create_errdialog(self, error_msg: str, detail_traceback: str = '', exception_type: str = ''):
try:
Expand Down
6 changes: 5 additions & 1 deletion ui/mainwindowbars.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ def __init__(self, mainwindow, *args, **kwargs) -> None:
actionExportTranslationMD = QAction(self.tr("Export translation as markdown"), self)
self.export_trans_md = actionExportTranslationMD.triggered

actionImportTranslationTxt = QAction(self.tr("Import translation from TXT/markdown"), self)
self.import_trans_txt = actionImportTranslationTxt.triggered

self.recentMenu = QMenu(self.tr("Open Recent"), self)

openMenu = QMenu(self)
Expand All @@ -168,6 +171,7 @@ def __init__(self, mainwindow, *args, **kwargs) -> None:
actionExportTranslationTxt,
actionExportSrcMD,
actionExportTranslationMD,
actionImportTranslationTxt,
])
self.openBtn = OpenBtn()
self.openBtn.setFixedSize(LEFTBTN_WIDTH, LEFTBTN_WIDTH)
Expand All @@ -181,7 +185,7 @@ def __init__(self, mainwindow, *args, **kwargs) -> None:
self.runImgtransBtn = QPushButton()
self.runImgtransBtn.setText(self.tr('RUN'))
self.runImgtransBtn.setFixedSize(LEFTBTN_WIDTH, LEFTBTN_WIDTH)
self.run_imgtrans = self.runImgtransBtn.clicked
self.run_imgtrans_clicked = self.runImgtransBtn.clicked
self.runImgtransBtn.setFixedSize(LEFTBTN_WIDTH, LEFTBTN_WIDTH)

vlayout = QVBoxLayout(self)
Expand Down
17 changes: 1 addition & 16 deletions ui/module_parse_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from modules import GET_VALID_INPAINTERS, GET_VALID_TEXTDETECTORS, GET_VALID_TRANSLATORS, GET_VALID_OCR, \
BaseTranslator, DEFAULT_DEVICE, GPUINTENSIVE_SET
from utils.logger import logger as LOGGER
from .custom_widget import ConfigComboBox, ParamComboBox, NoBorderPushBtn
from .custom_widget import ConfigComboBox, ParamComboBox, NoBorderPushBtn, ParamNameLabel
from utils.shared import CONFIG_FONTSIZE_CONTENT, CONFIG_COMBOBOX_MIDEAN, CONFIG_COMBOBOX_LONG, CONFIG_COMBOBOX_SHORT, CONFIG_COMBOBOX_HEIGHT
from utils.config import pcfg

Expand All @@ -12,21 +12,6 @@
from qtpy.QtGui import QDoubleValidator


class ParamNameLabel(QLabel):
def __init__(self, param_name: str, alignment = None, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)

if alignment is None:
self.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
else:
self.setAlignment(alignment)

font = self.font()
font.setPointSizeF(CONFIG_FONTSIZE_CONTENT-2)
self.setFont(font)
self.setText(param_name)
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground, True)

class ParamLineEditor(QLineEdit):

paramwidget_edited = Signal(str, str)
Expand Down
1 change: 1 addition & 0 deletions ui/scenetext_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ def clearSceneTextitems(self):
self.pairwidget_list.clear()

def updateSceneTextitems(self):
self.hovering_transwidget = None
self.txtblkShapeControl.setBlkItem(None)
self.clearSceneTextitems()
for textblock in self.imgtrans_proj.current_block_list():
Expand Down
Loading

0 comments on commit 042486b

Please sign in to comment.