From e5df10d21f972f3f1b339bc1a8cd2db01f1e2663 Mon Sep 17 00:00:00 2001 From: bookfere Date: Mon, 20 Nov 2023 02:56:40 +0800 Subject: [PATCH] feat: Show the count of paragraphs and their character count. resolved #130 --- README.md | 2 +- README.zh-CN.md | 2 +- advanced.py | 66 +++++++++++++++++++++++++++++---------------- components/table.py | 10 ++++--- 4 files changed, 51 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 309a429..02325d7 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ __Plugin Homepage__: [https://translator.bookfere.com](https://translator.bookfe * Support languages supported by the selected translation engine (e.g. Google Translate supports 134 languages) * Support multiple translation engines, including Google Translate, ChatGPT, DeepL, etc. * Support custom translation engines (you can configure to parse response in JSON or XML format) -* Support all ebook formats supported by Calibre (48 input formats, 20 output formats) +* Support all ebook formats supported by Calibre (48 input formats, 20 output formats), as well as additional formats such as .srt * Support to translate more than one ebooks. The translation process of each book is carried out simultaneously without affecting one another * Support caching translated content, with no need to re-translate after request failure or network interruption * Provide a large number of customization settings, such as saving translated ebooks to Calibre library or designated location diff --git a/README.zh-CN.md b/README.zh-CN.md index 87cc4e8..fb3ea2c 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -17,7 +17,7 @@ __插件主页__:[https://translator.bookfere.com](https://translator.bookfere * 支持所选翻译引擎所支持的语言(如 Google 翻译支持 134 种) * 支持多种翻译引擎,包括 Google 翻译、ChatGPT、DeepL 等 * 支持自定义翻译引擎(支持解析 JSON 和 XML 格式响应) -* 支持所有 Calibre 所支持的电子书格式(输入格式 48 种,输出格式 20 种) +* 支持所有 Calibre 所支持的电子书格式(输入 48 种,输出 20 种)以及 .srt 等额外格式 * 支持批量翻译电子书,每本书的翻译过程同时进行互不影响 * 支持缓存翻译内容,在请求失败或网络中断后无需重新翻译 * 提供大量自定义设置,如将翻译的电子书存到 Calibre 书库或指定位置 diff --git a/advanced.py b/advanced.py index 8678471..4b33dfd 100644 --- a/advanced.py +++ b/advanced.py @@ -298,7 +298,7 @@ def working_status(): def working_finished(): if self.translate_all and not self.trans_worker.cancel_request(): - failures = len(self.table.get_seleted_items(True, True)) + failures = len(self.table.get_selected_items(True, True)) if failures > 0: message = _( 'Failed to translate {} paragraph(s), ' @@ -440,23 +440,43 @@ def layout_table_control(self): action_layout = QHBoxLayout(action_widget) action_layout.setContentsMargins(0, 0, 0, 0) + delete_button = QPushButton(_('Delete')) + paragraph_count = QLabel() + paragraph_count.setAlignment(Qt.AlignCenter) translate_all = QPushButton(' %s ' % _('Translate All')) translate_selected = QPushButton(' %s ' % _('Translate Selected')) - delete_button = QPushButton(_('Delete')) + delete_button.clicked.connect(self.table.delete_by_rows) translate_all.clicked.connect(self.translate_all_paragraphs) translate_selected.clicked.connect(self.translate_selected_paragraph) - self.table.itemSelectionChanged.connect( - lambda: translate_selected.setDisabled( - self.table.selected_count() < 1)) - delete_button.clicked.connect(self.table.delete_by_rows) - self.table.itemSelectionChanged.connect( - lambda: delete_button.setDisabled( - self.table.selected_count() < 1)) + delete_button.setDisabled(True) + translate_selected.setDisabled(True) + + def get_paragraph_count(select_all=True): + item_count = char_count = 0 + paragraphs = self.table.get_selected_items(select_all=select_all) + for paragraph in paragraphs: + item_count += 1 + char_count += len(paragraph.original) + return (item_count, char_count) + all_item_count, all_char_count = get_paragraph_count(True) + + def item_selection_changed(): + disabled = self.table.selected_count() < 1 + delete_button.setDisabled(disabled) + translate_selected.setDisabled(disabled) + item_count, char_count = get_paragraph_count(False) + total = '%s/%s' % (item_count, all_item_count) + parts = '%s/%s' % (char_count, all_char_count) + paragraph_count.setText( + _('Total items: {}').format(total) + ' · ' + + _('Character count: {}').format(parts)) + item_selection_changed() + self.table.itemSelectionChanged.connect(item_selection_changed) action_layout.addWidget(delete_button) - action_layout.addStretch(1) + action_layout.addWidget(paragraph_count, 1) action_layout.addWidget(translate_all) action_layout.addWidget(translate_selected) @@ -678,6 +698,8 @@ def change_selected_item(): if self.on_working: return paragraph = self.table.current_paragraph() + if paragraph is None: + return self.raw_text.emit(paragraph.raw) self.original_text.emit(paragraph.original.strip()) self.translation_text[str].emit(paragraph.translation) @@ -691,10 +713,7 @@ def translation_callback(paragraph): self.raw_text.emit(paragraph.raw) self.original_text.emit(paragraph.original) self.translation_text[str].emit(paragraph.translation) - try: - self.cache.update_paragraph(paragraph) - except Exception as e: - raise e + self.cache.update_paragraph(paragraph) self.progress_bar.emit() self.trans_worker.callback.connect(translation_callback) @@ -708,11 +727,12 @@ def streaming_translation(data): self.trans_worker.streaming.connect(streaming_translation) def modify_translation(): - if not self.on_working: - paragraph = self.table.current_paragraph() - translation = translation_text.toPlainText() - control.setVisible( - bool(translation) and translation != paragraph.translation) + if self.on_working and self.table.selected_count() > 1: + return + paragraph = self.table.current_paragraph() + translation = translation_text.toPlainText() + control.setVisible( + bool(translation) and translation != paragraph.translation) translation_text.textChanged.connect(modify_translation) def save_translation(): @@ -761,10 +781,10 @@ def translate_all_paragraphs(self): """Translate the untranslated paragraphs when at least one is selected. Otherwise, retranslate all paragraphs regardless of prior translation. """ - paragraphs = self.table.get_seleted_items(True, True) + paragraphs = self.table.get_selected_items(True, True) is_fresh = len(paragraphs) < 1 if is_fresh: - paragraphs = self.table.get_seleted_items(False, True) + paragraphs = self.table.get_selected_items(False, True) self.prgress_step = self.get_progress_step(len(paragraphs)) if not self.translate_all: message = _( @@ -775,8 +795,8 @@ def translate_all_paragraphs(self): self.trans_worker.translate.emit(paragraphs, is_fresh) def translate_selected_paragraph(self): - paragraphs = self.table.get_seleted_items() - # If all paragraphs are selected, consider it as translating all. + paragraphs = self.table.get_selected_items() + # Consider selecting all paragraphs as translating all. if len(paragraphs) == self.table.rowCount(): self.translate_all_paragraphs() else: diff --git a/components/table.py b/components/table.py index 136b068..f5442dc 100644 --- a/components/table.py +++ b/components/table.py @@ -107,7 +107,9 @@ def paragraph(self, row): return paragraph def current_paragraph(self): - return self.paragraph(self.currentRow()) + # return self.paragraph(self.currentRow()) + items = self.get_selected_items() + return items[0] if len(items) > 0 else None def get_selected_rows(self): rows = [] @@ -119,7 +121,7 @@ def get_selected_rows(self): def selected_count(self): return len(self.get_selected_rows()) - def get_seleted_items(self, ignore_done=False, select_all=False): + def get_selected_items(self, ignore_done=False, select_all=False): items = [] rows = range(self.rowCount()) if select_all else \ self.get_selected_rows() @@ -146,7 +148,7 @@ def delete_by_rows(self, rows=[]): def select_by_attribute(self, name, value): rows = [] - paragraphs = self.get_seleted_items(False, True) + paragraphs = self.get_selected_items(False, True) for paragraph in paragraphs: attributes = paragraph.get_attributes() if attributes.get(name) == value: @@ -157,7 +159,7 @@ def select_by_attribute(self, name, value): def select_by_page(self, page): rows = [] - paragraphs = self.get_seleted_items(False, True) + paragraphs = self.get_selected_items(False, True) for paragraph in paragraphs: if paragraph.page == page: rows.append(paragraph.row)