Skip to content

Commit 492e115

Browse files
author
Tolkachev Aleksei
committed
panel with blocks navigation and save/load current state
1 parent 083beeb commit 492e115

File tree

3 files changed

+145
-4
lines changed

3 files changed

+145
-4
lines changed

app/ui/main_window.py

+30
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ def _create_main_content(self):
264264
s_combo_text_layout.addWidget(self.s_combo)
265265
self.s_text_edit = MTextEdit()
266266
self.s_text_edit.setFixedHeight(200)
267+
self.s_text_edit.installEventFilter(self)
267268
s_combo_text_layout.addWidget(self.s_text_edit)
268269
input_layout.addLayout(s_combo_text_layout)
269270

@@ -275,6 +276,7 @@ def _create_main_content(self):
275276
t_combo_text_layout.addWidget(self.t_combo)
276277
self.t_text_edit = MTextEdit()
277278
self.t_text_edit.setFixedHeight(200)
279+
self.t_text_edit.installEventFilter(self)
278280
t_combo_text_layout.addWidget(self.t_text_edit)
279281

280282
# Font Settings
@@ -325,6 +327,28 @@ def _create_main_content(self):
325327

326328
input_layout.addLayout(t_combo_text_layout)
327329

330+
self.load_blocks_state_button = MClickBrowserFileToolButton(multiple=False)
331+
self.load_blocks_state_button.set_dayu_svg("folder_fill.svg")
332+
self.load_blocks_state_button.set_dayu_filters([".txt"])
333+
self.load_blocks_state_button.setToolTip(self.tr("Import text file with translations"))
334+
self.load_blocks_state_button.sig_file_changed.connect(self.load_blocks_state)
335+
336+
blocks_layout = QtWidgets.QHBoxLayout()
337+
self.blocks_checker_group = MToolButtonGroup(orientation=QtCore.Qt.Horizontal, exclusive=False)
338+
blocks_checker_buttons = [
339+
{"text": self.tr("Previous"), "svg": "left_fill.svg", "checkable": False, "tooltip": self.tr("Previous block"), "clicked": self.select_prev_text},
340+
{"text": self.tr("Next"), "svg": "right_fill.svg", "checkable": False, "tooltip": self.tr("Next block"), "clicked": self.select_next_text},
341+
{"text": self.tr("Save state"), "svg": "save_fill.svg", "checkable": False, "tooltip": self.tr("Backup all blocks to file"), "clicked": self.save_blocks_state},
342+
{"text": self.tr("Load saved"), "svg": "folder_fill.svg", "checkable": False, "tooltip": self.tr("Import blocks from file"), "clicked": self.load_blocks_button},
343+
]
344+
self.blocks_checker_group.set_button_list(blocks_checker_buttons)
345+
blocks_layout.addWidget(self.blocks_checker_group)
346+
blocks_panel_layout = QtWidgets.QVBoxLayout()
347+
blocks_panel_header = MDivider(self.tr('Actions with text blocks'))
348+
blocks_panel_layout.addWidget(blocks_panel_header)
349+
blocks_panel_layout.addLayout(blocks_layout)
350+
blocks_panel_layout.addSpacing(20)
351+
328352
# Tools Layout
329353
tools_widget = QtWidgets.QWidget()
330354
tools_layout = QtWidgets.QVBoxLayout()
@@ -473,6 +497,7 @@ def _create_main_content(self):
473497

474498
right_layout.addLayout(input_layout)
475499
right_layout.addLayout(font_panel_layout)
500+
right_layout.addLayout(blocks_panel_layout)
476501
right_layout.addWidget(tools_scroll)
477502
right_layout.addStretch()
478503

@@ -652,3 +677,8 @@ def brush_redo(self):
652677
def delete_selected_box(self):
653678
self.image_viewer.delete_selected_rectangle()
654679

680+
def eventFilter(self, obj, event):
681+
if event.type() == QtCore.QEvent.KeyPress and event.key() == QtCore.Qt.Key_Tab:
682+
event.ignore()
683+
self.select_next_text()
684+
return True

comic.py

+114-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
import cv2, shutil
3+
import json
34
import tempfile
45
import numpy as np
56
from typing import Callable, Tuple, List
@@ -19,6 +20,8 @@
1920
from app.thread_worker import GenericWorker
2021
from app.ui.dayu_widgets.message import MMessage
2122

23+
from datetime import datetime
24+
2225
from modules.detection import do_rectangles_overlap, get_inpaint_bboxes
2326
from modules.utils.textblock import TextBlock
2427
from modules.rendering.render import draw_text
@@ -47,6 +50,7 @@ def __init__(self, parent=None):
4750
self.image_states = {}
4851

4952
self.blk_list = []
53+
self.cleaned_image = None # Store cleaned image
5054
self.image_data = {} # Store the latest version of each image
5155
self.image_history = {} # Store undo/redo history for each image
5256
self.current_history_index = {} # Current position in the undo/redo history for each image
@@ -162,18 +166,122 @@ def set_block_font_settings(self):
162166
if blk.max_font_size > 0:
163167
self.max_font_spinbox.setValue(blk.max_font_size)
164168

169+
def get_current_block_index(self):
170+
if self.current_text_block:
171+
return self.blk_list.index(self.current_text_block)
172+
return 0
173+
174+
def select_prev_text(self):
175+
if len(self.blk_list) == 0:
176+
return
177+
current_block_index = self.get_current_block_index()
178+
if current_block_index == 0:
179+
block_index = -1
180+
else:
181+
block_index = current_block_index - 1
182+
rect = self.find_corresponding_rect(self.blk_list[block_index], 0.5)
183+
if rect == None:
184+
return
185+
self.image_viewer.select_rectangle(rect)
186+
187+
def select_next_text(self):
188+
if len(self.blk_list) == 0:
189+
return
190+
current_block_index = self.get_current_block_index()
191+
if current_block_index == len(self.blk_list) - 1:
192+
block_index = 0
193+
else:
194+
block_index = current_block_index + 1
195+
rect = self.find_corresponding_rect(self.blk_list[block_index], 0.5)
196+
if rect == None:
197+
return
198+
self.image_viewer.select_rectangle(rect)
199+
200+
def save_blocks_state(self):
201+
if len(self.blk_list) == 0:
202+
return
203+
date_time = datetime.now().strftime("_%Y-%m-%d_%H-%M-%S")
204+
file_name_original = self.image_files[self.current_image_index]
205+
file_name = file_name_original[0:-4] + date_time + ".txt"
206+
a = open(file_name, 'w')
207+
208+
default_min_font_size = self.settings_page.get_min_font_size()
209+
default_init_font_size = self.settings_page.get_max_font_size()
210+
211+
for blk in self.blk_list:
212+
blk_rect = tuple(blk.xyxy)
213+
blk_rect_export = str(int(blk_rect[0])) + ',' + str(int(blk_rect[1])) + ',' + str(int(blk_rect[2])) + ',' + str(int(blk_rect[3]))
214+
215+
if blk.min_font_size > 0:
216+
min_font_size = blk.min_font_size
217+
else:
218+
min_font_size = default_min_font_size
219+
if blk.max_font_size > 0:
220+
init_font_size = blk.max_font_size
221+
else:
222+
init_font_size = default_init_font_size
223+
224+
blk_to_save = {
225+
'text': blk.text,
226+
'rect': blk_rect_export,
227+
'translation': blk.translation,
228+
'min_font_size': min_font_size,
229+
'init_font_size': init_font_size,
230+
}
231+
a.write(json.dumps(blk_to_save, ensure_ascii=False) + "\n")
232+
233+
a.close()
234+
dialog_message = "File " + file_name + " with data saved\n"
235+
236+
if self.cleaned_image is not None:
237+
cv2_img = self.cleaned_image #self.image_data[file_name_original]
238+
cv2_img_save = cv2.cvtColor(cv2_img, cv2.COLOR_BGR2RGB)
239+
sv_pth = file_name_original[0:-4] + date_time + '_cleaned' + file_name_original[-4:]
240+
cv2.imwrite(sv_pth, cv2_img_save)
241+
dialog_message += "File " + sv_pth + " with cleaned image saved\n"
242+
243+
dialog = QtWidgets.QDialog(self)
244+
dialog.setWindowTitle("Export completed successfully")
245+
label = QtWidgets.QLabel(dialog)
246+
label.setText(dialog_message)
247+
label.setMargin(20)
248+
label.adjustSize()
249+
dialog.exec_()
250+
251+
def load_blocks_button(self):
252+
self.load_blocks_state_button.click()
253+
254+
def load_blocks_state(self, file_path: str):
255+
updated_blk_list = []
256+
with open(file_path, 'r') as f:
257+
for line in f.readlines():
258+
blk_to_load = json.loads(line)
259+
blk_rect_coord = blk_to_load['rect'].split(',')
260+
new_blk_coord = [int(blk_rect_coord[0]), int(blk_rect_coord[1]), int(blk_rect_coord[2]), int(blk_rect_coord[3])]
261+
new_blk = TextBlock(new_blk_coord)
262+
new_blk.translation = blk_to_load['translation']
263+
new_blk.text = blk_to_load['text']
264+
new_blk.min_font_size = blk_to_load['min_font_size']
265+
new_blk.init_font_size = blk_to_load['init_font_size']
266+
updated_blk_list.append(new_blk)
267+
268+
self.blk_list = updated_blk_list
269+
self.pipeline.load_box_coords(self.blk_list)
270+
165271
def batch_mode_selected(self):
166272
self.disable_hbutton_group()
167273
self.translate_button.setEnabled(True)
168274
self.cancel_button.setEnabled(True)
169275
self.set_manual_font_settings_enabled(False)
276+
self.blocks_checker_group.setVisible(False)
170277

171278
def manual_mode_selected(self):
172279
self.enable_hbutton_group()
173280
self.translate_button.setEnabled(False)
174281
self.cancel_button.setEnabled(False)
175282
self.set_manual_font_settings_enabled(True)
176-
283+
self.blocks_checker_group.setVisible(True)
284+
177285
def on_image_processed(self, index: int, rendered_image: np.ndarray, image_path: str):
178286
if index == self.current_image_index:
179287
self.set_cv2_image(rendered_image)
@@ -395,7 +503,8 @@ def save_image_state(self, file: str):
395503
'target_text': self.t_text_edit.toPlainText(),
396504
'target_lang': self.t_combo.currentText(),
397505
'brush_strokes': self.image_viewer.save_brush_strokes(),
398-
'blk_list': self.blk_list
506+
'blk_list': self.blk_list,
507+
'cleaned_image': self.cleaned_image,
399508
}
400509

401510
def save_current_image_state(self):
@@ -416,6 +525,7 @@ def load_image_state(self, file_path: str):
416525
self.t_combo.setCurrentText(state['target_lang'])
417526
self.image_viewer.load_brush_strokes(state['brush_strokes'])
418527
self.blk_list = state['blk_list']
528+
self.cleaned_image = state['cleaned_image']
419529
else:
420530
self.s_text_edit.clear()
421531
self.t_text_edit.clear()
@@ -764,7 +874,7 @@ def get_system_language():
764874
'ko': '한국어',
765875
'fr': 'Français',
766876
'ja': '日本語',
767-
'ru': 'русский',
877+
'ru': 'Русский',
768878
'de': 'Deutsch',
769879
'nl': 'Nederlands',
770880
'es': 'Español',
@@ -783,7 +893,7 @@ def load_translation(app, language: str):
783893
'日本語': 'ja',
784894
'简体中文': 'zh_CN',
785895
'繁體中文': 'zh_TW',
786-
'русский': 'ru',
896+
'Русский': 'ru',
787897
'Deutsch': 'de',
788898
'Nederlands': 'nl',
789899
'Español': 'es',

pipeline.py

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ def manual_inpaint(self):
8383
def inpaint_complete(self, result):
8484
inpainted, original_image = result
8585
self.main_page.set_cv2_image(inpainted)
86+
self.main_page.cleaned_image = inpainted
8687
# get_best_render_area(self.main_page.blk_list, original_image, inpainted)
8788
self.load_box_coords(self.main_page.blk_list)
8889

0 commit comments

Comments
 (0)