Skip to content

Commit

Permalink
feat: Allow users to choose the text direction for translated text. r…
Browse files Browse the repository at this point in the history
…esolved #209
  • Loading branch information
bookfere committed May 1, 2024
1 parent 9ab6e59 commit a5d219c
Show file tree
Hide file tree
Showing 16 changed files with 452 additions and 287 deletions.
60 changes: 36 additions & 24 deletions advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ def prepare_ebook_data(self):
self.on_working = True
input_path = self.ebook.get_input_path()
element_handler = get_element_handler(
self.engine_class.placeholder, self.engine_class.separator)
self.engine_class.placeholder, self.engine_class.separator,
self.ebook.target_direction)
merge_length = str(element_handler.get_merge_length())
encoding = ''
if self.ebook.encoding.lower() != 'utf-8':
Expand Down Expand Up @@ -254,6 +255,7 @@ def layout_format(self):
input_format = InputFormat(self.ebook.files.keys())
input_format.setFixedWidth(150)
input_layout.addWidget(input_format)
layout.addWidget(input_group)

def change_input_format(format):
self.ebook.set_input_format(format)
Expand All @@ -265,6 +267,7 @@ def change_input_format(format):
target_lang = TargetLang()
target_lang.setFixedWidth(150)
target_layout.addWidget(target_lang)
layout.addWidget(target_group)

engine_class = get_engine_class()
target_lang.refresh.emit(
Expand All @@ -276,21 +279,31 @@ def change_target_format(format):
change_target_format(target_lang.currentText())
target_lang.currentTextChanged.connect(change_target_format)

encoding_group = QGroupBox(_('Encoding'))
encoding_layout = QVBoxLayout(encoding_group)
encoding_select = QComboBox()
encoding_select.addItems(encoding_list)
encoding_layout.addWidget(encoding_select)
encoding_group.setVisible(
self.ebook.input_format in extra_formats.keys())

def change_encoding(encoding):
self.ebook.set_encoding(encoding)
encoding_select.currentTextChanged.connect(change_encoding)

layout.addWidget(input_group)
layout.addWidget(target_group)
layout.addWidget(encoding_group)
if self.ebook.input_format in extra_formats.keys():
encoding_group = QGroupBox(_('Encoding'))
encoding_layout = QVBoxLayout(encoding_group)
encoding_select = QComboBox()
encoding_select.addItems(encoding_list)
encoding_layout.addWidget(encoding_select)
layout.addWidget(encoding_group)

def change_encoding(encoding):
self.ebook.set_encoding(encoding)
encoding_select.currentTextChanged.connect(change_encoding)
else:
direction_group = QGroupBox(_('Target Directionality'))
direction_layout = QVBoxLayout(direction_group)
direction_list = QComboBox()
direction_list.addItem(_('Auto'), 'auto')
direction_list.addItem(_('Left to Right'), 'ltr')
direction_list.addItem(_('Right to Left'), 'rtl')
direction_layout.addWidget(direction_list)
layout.addWidget(direction_group)

def change_direction(index):
direction = direction_list.itemData(index)
self.ebook.set_target_direction(direction)
direction_list.currentIndexChanged.connect(change_direction)

return widget

Expand Down Expand Up @@ -771,20 +784,19 @@ def change_ebook_title():
# 'Calibre Library.'))
# ebook_title.textChanged.connect(self.ebook.set_custom_title)

save_group = QGroupBox(_('Output Ebook'))
save_layout = QHBoxLayout(save_group)
save_ebook = QPushButton(_('Output'))
output_group = QGroupBox(_('Output Ebook'))
output_layout = QHBoxLayout(output_group)
output_button = QPushButton(_('Output'))
output_format = OutputFormat()
# save_layout.addWidget(QLabel(_('Format')))
save_layout.addWidget(output_format)
save_layout.addWidget(save_ebook)
output_layout.addWidget(output_format)
output_layout.addWidget(output_button)

layout.addWidget(cache_group)
layout.addWidget(engine_group)
layout.addWidget(source_group)
layout.addWidget(target_group)
layout.addWidget(title_group, 1)
layout.addWidget(save_group)
layout.addWidget(output_group)

source_lang.currentTextChanged.connect(
self.trans_worker.set_source_lang)
Expand Down Expand Up @@ -836,7 +848,7 @@ def output_ebook():
self.ebook.set_lang_code(lang_code)
self.worker.translate_ebook(self.ebook, cache_only=True)
self.done(1)
save_ebook.clicked.connect(output_ebook)
output_button.clicked.connect(output_ebook)

def working_start():
self.translate_all and widget.setVisible(False)
Expand Down
23 changes: 20 additions & 3 deletions batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def _cell_widget(self, _widget):
layout = QHBoxLayout(widget)
layout.setContentsMargins(5, 5, 5, 5)
# _widget.setFixedSize(_widget.sizeHint())
_widget.setFixedHeight(_widget.sizeHint().height())
# _widget.setFixedHeight(_widget.sizeHint().height())
layout.addWidget(_widget, 1)
# layout.setAlignment(_widget, Qt.AlignCenter)
return widget
Expand All @@ -69,15 +69,16 @@ def layout_translate(self):

headers = (
_('Title'), _('Encoding'), _('Input Format'), _('Output Format'),
_('Source Language'), _('Target Language'))
_('Source Language'), _('Target Language'),
_('Target Directionality'))
table.setColumnCount(len(headers))
table.setHorizontalHeaderLabels(headers)

header = table.horizontalHeader()
stretch = getattr(QHeaderView.ResizeMode, 'Stretch', None) \
or QHeaderView.Stretch
header.setSectionResizeMode(0, stretch)
# table.verticalHeader().setMinimumSectionSize(36)
table.verticalHeader().setMaximumSectionSize(36)

translation_engine = get_engine_class()
for row, ebook in enumerate(self.ebooks):
Expand All @@ -94,10 +95,26 @@ def layout_translate(self):
.set_encoding(encoding))
input_encoding.currentTextChanged.connect(
lambda encoding: input_encoding.setToolTip(encoding))
# Target directionality
target_direction = QTableWidgetItem(_('Default'))
target_direction.setTextAlignment(Qt.AlignCenter)
table.setItem(row, 6, target_direction)
else:
input_encoding = QTableWidgetItem(_('Default'))
input_encoding.setTextAlignment(Qt.AlignCenter)
table.setItem(row, 1, input_encoding)
# Target directionality
direction_list = QComboBox()
direction_list.wheelEvent = lambda event: None
direction_list.addItem(_('Auto'), 'auto')
direction_list.addItem(_('Left to Right'), 'ltr')
direction_list.addItem(_('Right to Left'), 'rtl')
direction_list.currentIndexChanged.connect(
lambda index, row=row: self.ebooks[row]
.set_target_direction(direction_list.itemData(index)))
direction_list.currentTextChanged.connect(
lambda direction: direction_list.setToolTip(direction))
table.setCellWidget(row, 6, self._cell_widget(direction_list))

input_fmt = InputFormat(ebook.files.keys())
table.setCellWidget(row, 2, self._cell_widget(input_fmt))
Expand Down
7 changes: 3 additions & 4 deletions lib/conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def convert(self, oeb, output_path, input_plugin, opts, log):

def convert_item(
ebook_title, input_path, output_path, source_lang, target_lang,
cache_only, is_batch, format, encoding, notification):
cache_only, is_batch, format, encoding, direction, notification):
"""The following parameters need attention:
:cache_only: Only use the translation which exists in the cache.
:notification: It is automatically added by arbitrary_n.
Expand All @@ -190,7 +190,7 @@ def convert_item(
translator.set_target_lang(target_lang)

element_handler = get_element_handler(
translator.placeholder, translator.separator)
translator.placeholder, translator.separator, direction)
element_handler.set_translation_lang(
translator.get_iso639_target_code(target_lang))

Expand Down Expand Up @@ -256,7 +256,6 @@ def translate_ebook(self, ebook, cache_only=False, is_batch=False):
else:
output_path = PersistentTemporaryFile(
suffix='.' + ebook.output_format).name

job = self.gui.job_manager.run_job(
Dispatcher(self.translate_done),
'arbitrary_n',
Expand All @@ -265,7 +264,7 @@ def translate_ebook(self, ebook, cache_only=False, is_batch=False):
'convert_item',
(ebook.title, input_path, output_path, ebook.source_lang,
ebook.target_lang, cache_only, is_batch, ebook.input_format,
ebook.encoding)),
ebook.encoding, ebook.target_direction)),
description=(_('[{} > {}] Translating "{}"').format(
ebook.source_lang, ebook.target_lang, ebook.title)))
self.working_jobs[job] = (ebook, output_path)
Expand Down
4 changes: 4 additions & 0 deletions lib/ebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def __init__(self, id, title, files, input_format, source_lang,
self.title = title
self.custom_title = None
self.encoding = 'utf-8'
self.target_direction = 'auto'

def set_input_format(self, format):
self.input_format = format
Expand All @@ -37,6 +38,9 @@ def set_custom_title(self, title):
def set_encoding(self, encoding):
self.encoding = encoding

def set_target_direction(self, direction):
self.target_direction = direction

def get_input_path(self):
return self.files.get(self.input_format)

Expand Down
27 changes: 21 additions & 6 deletions lib/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def __init__(self, element, page_id=None, ignored=False):
self.column_gap = None

self.position = None
self.target_direction = None
self.translation_lang = None
self.original_color = None
self.translation_color = None
Expand All @@ -55,6 +56,9 @@ def set_column_gap(self, values):
def set_position(self, position):
self.position = position

def set_target_direction(self, direction):
self.target_direction = direction

def set_translation_lang(self, lang):
self.translation_lang = lang

Expand Down Expand Up @@ -249,7 +253,7 @@ def _create_new_element(
name in excluding_attrs:
continue
new_element.set(name, value)
new_element.set('dir', 'auto')
new_element.set('dir', self.target_direction or 'auto')
if self.translation_lang is not None:
new_element.set('lang', self.translation_lang)
if self.translation_color is not None:
Expand Down Expand Up @@ -578,11 +582,13 @@ def filter_content(self, element):


class ElementHandler:
def __init__(self, placeholder, separator, position, merge_length=0):
def __init__(self, placeholder, separator, position):
self.placeholder = placeholder
self.separator = separator
self.position = position
self.merge_length = merge_length

self.merge_length = 0
self.target_direction = None

self.translation_lang = None
self.original_color = None
Expand All @@ -595,9 +601,15 @@ def __init__(self, placeholder, separator, position, merge_length=0):
self.elements = {}
self.originals = []

def set_merge_length(self, length):
self.merge_length = length

def get_merge_length(self):
return self.merge_length

def set_target_direction(self, direction):
self.target_direction = direction

def set_translation_lang(self, lang):
self.translation_lang = lang

Expand Down Expand Up @@ -628,6 +640,7 @@ def prepare_original(self, elements):
for oid, element in enumerate(elements):
element.set_placeholder(self.placeholder)
element.set_position(self.position)
element.set_target_direction(self.target_direction)
element.set_translation_lang(self.translation_lang)
element.set_original_color(self.original_color)
element.set_translation_color(self.translation_color)
Expand Down Expand Up @@ -679,6 +692,7 @@ def prepare_original(self, elements):
continue
element.set_placeholder(self.placeholder)
element.set_position(self.position)
element.set_target_direction(self.target_direction)
element.set_translation_lang(self.translation_lang)
element.set_original_color(self.original_color)
element.set_translation_color(self.translation_color)
Expand Down Expand Up @@ -802,15 +816,16 @@ def get_page_elements(pages):
return extraction.get_elements()


def get_element_handler(placeholder, separator):
def get_element_handler(placeholder, separator, direction):
config = get_config()
position_alias = {'before': 'above', 'after': 'below'}
position = config.get('translation_position', 'below')
position = position_alias.get(position) or position
handler = ElementHandler(placeholder, separator, position)
if config.get('merge_enabled'):
handler = ElementHandlerMerge(
placeholder, separator, position, config.get('merge_length'))
handler = ElementHandlerMerge(placeholder, separator, position)
handler.set_merge_length(config.get('merge_length'))
handler.set_target_direction(direction)
column_gap = config.get('column_gap')
gap_type = column_gap.get('_type')
if gap_type is not None and gap_type in column_gap.keys():
Expand Down

0 comments on commit a5d219c

Please sign in to comment.