Reformat using black

This commit is contained in:
Deniz Şafak
2025-11-19 01:54:11 +03:00
parent 43f5589a9d
commit bb5c4204de
8 changed files with 572 additions and 311 deletions
+3 -1
View File
@@ -377,9 +377,10 @@ class HandlerDialog(QDialog):
# Include replace_single_newlines in cache key since it affects text cleaning # Include replace_single_newlines in cache key since it affects text cleaning
from abogen.utils import load_config from abogen.utils import load_config
cfg = load_config() cfg = load_config()
replace_single_newlines = cfg.get("replace_single_newlines", False) replace_single_newlines = cfg.get("replace_single_newlines", False)
cache_key = (self.book_path, mod_time, self.file_type, replace_single_newlines) cache_key = (self.book_path, mod_time, self.file_type, replace_single_newlines)
# Check if content is already cached # Check if content is already cached
@@ -2240,6 +2241,7 @@ class HandlerDialog(QDialog):
if metadata.get("cover_image"): if metadata.get("cover_image"):
try: try:
import uuid import uuid
cache_dir = get_user_cache_path() cache_dir = get_user_cache_path()
cover_path = os.path.join(cache_dir, f"cover_{uuid.uuid4()}.jpg") cover_path = os.path.join(cache_dir, f"cover_{uuid.uuid4()}.jpg")
cover_path = os.path.normpath(cover_path) cover_path = os.path.normpath(cover_path)
+1 -3
View File
@@ -2,9 +2,7 @@ from abogen.utils import get_version
# Program Information # Program Information
PROGRAM_NAME = "abogen" PROGRAM_NAME = "abogen"
PROGRAM_DESCRIPTION = ( PROGRAM_DESCRIPTION = "Generate audiobooks from EPUBs, PDFs, text and subtitles with synchronized captions."
"Generate audiobooks from EPUBs, PDFs, text and subtitles with synchronized captions."
)
GITHUB_URL = "https://github.com/denizsafak/abogen" GITHUB_URL = "https://github.com/denizsafak/abogen"
VERSION = get_version() VERSION = get_version()
+494 -264
View File
File diff suppressed because it is too large Load Diff
+46 -31
View File
@@ -337,12 +337,12 @@ class InputBox(QLabel):
self.edit_btn.setVisible(should_show_edit) self.edit_btn.setVisible(should_show_edit)
self.go_to_folder_btn.show() self.go_to_folder_btn.show()
# Disable subtitle generation for subtitle input files # Disable subtitle generation for subtitle input files
is_subtitle_input = file_path.lower().endswith((".srt", ".ass", ".vtt")) is_subtitle_input = file_path.lower().endswith((".srt", ".ass", ".vtt"))
if hasattr(window, "subtitle_combo"): if hasattr(window, "subtitle_combo"):
window.subtitle_combo.setEnabled(not is_subtitle_input) window.subtitle_combo.setEnabled(not is_subtitle_input)
# Enable add to queue button only when file is accepted (input box is green) # Enable add to queue button only when file is accepted (input box is green)
self.resizeEvent(None) self.resizeEvent(None)
if hasattr(window, "btn_add_to_queue"): if hasattr(window, "btn_add_to_queue"):
@@ -385,16 +385,18 @@ class InputBox(QLabel):
self.textbox_btn.show() self.textbox_btn.show()
self.edit_btn.hide() self.edit_btn.hide()
self.go_to_folder_btn.hide() self.go_to_folder_btn.hide()
# Re-enable subtitle and replace newlines controls when cleared # Re-enable subtitle and replace newlines controls when cleared
window = self.window() window = self.window()
if hasattr(window, "subtitle_combo"): if hasattr(window, "subtitle_combo"):
# Only enable if language supports it # Only enable if language supports it
current_lang = getattr(window, "lang_code", "a") current_lang = getattr(window, "lang_code", "a")
window.subtitle_combo.setEnabled(current_lang in SUPPORTED_LANGUAGES_FOR_SUBTITLE_GENERATION) window.subtitle_combo.setEnabled(
current_lang in SUPPORTED_LANGUAGES_FOR_SUBTITLE_GENERATION
)
if hasattr(window, "replace_newlines_combo"): if hasattr(window, "replace_newlines_combo"):
window.replace_newlines_combo.setEnabled(True) window.replace_newlines_combo.setEnabled(True)
# Disable add to queue button when input is cleared # Disable add to queue button when input is cleared
if hasattr(window, "btn_add_to_queue"): if hasattr(window, "btn_add_to_queue"):
window.btn_add_to_queue.setEnabled(False) window.btn_add_to_queue.setEnabled(False)
@@ -502,7 +504,9 @@ class InputBox(QLabel):
) )
event.acceptProposedAction() event.acceptProposedAction()
else: else:
self.set_error("Please drop a .txt, .epub, .pdf, .md, .srt, .ass, or .vtt file.") self.set_error(
"Please drop a .txt, .epub, .pdf, .md, .srt, .ass, or .vtt file."
)
event.ignore() event.ignore()
else: else:
event.ignore() event.ignore()
@@ -1318,7 +1322,10 @@ class abogen(QWidget):
return return
try: try:
file_path, _ = QFileDialog.getOpenFileName( file_path, _ = QFileDialog.getOpenFileName(
self, "Select File", "", "Supported Files (*.txt *.epub *.pdf *.md *.srt *.ass *.vtt)" self,
"Select File",
"",
"Supported Files (*.txt *.epub *.pdf *.md *.srt *.ass *.vtt)",
) )
if not file_path: if not file_path:
return return
@@ -1934,9 +1941,7 @@ class abogen(QWidget):
self.replace_single_newlines = getattr( self.replace_single_newlines = getattr(
queued_item, "replace_single_newlines", False queued_item, "replace_single_newlines", False
) )
self.use_silent_gaps = getattr( self.use_silent_gaps = getattr(queued_item, "use_silent_gaps", False)
queued_item, "use_silent_gaps", False
)
# Restore the original file path for save location # Restore the original file path for save location
self.displayed_file_path = ( self.displayed_file_path = (
queued_item.save_base_path or queued_item.file_name queued_item.save_base_path or queued_item.file_name
@@ -2083,9 +2088,7 @@ class abogen(QWidget):
self.replace_single_newlines self.replace_single_newlines
) )
# Pass use_silent_gaps setting # Pass use_silent_gaps setting
self.conversion_thread.use_silent_gaps = ( self.conversion_thread.use_silent_gaps = self.use_silent_gaps
self.use_silent_gaps
)
# Pass subtitle_speed_method setting # Pass subtitle_speed_method setting
self.conversion_thread.subtitle_speed_method = self.subtitle_speed_method self.conversion_thread.subtitle_speed_method = self.subtitle_speed_method
# Pass separate_chapters_format setting # Pass separate_chapters_format setting
@@ -2813,17 +2816,20 @@ class abogen(QWidget):
# Check if this is a timestamp detection (-1) or chapter detection # Check if this is a timestamp detection (-1) or chapter detection
if chapter_count == -1: if chapter_count == -1:
from abogen.conversion import TimestampDetectionDialog from abogen.conversion import TimestampDetectionDialog
dialog = TimestampDetectionDialog(parent=self) dialog = TimestampDetectionDialog(parent=self)
dialog.setWindowModality(Qt.WindowModality.ApplicationModal) dialog.setWindowModality(Qt.WindowModality.ApplicationModal)
# Dialog always accepts (Yes or No), never cancels the conversion # Dialog always accepts (Yes or No), never cancels the conversion
dialog.exec() dialog.exec()
treat_as_subtitle = dialog.use_timestamps() treat_as_subtitle = dialog.use_timestamps()
if hasattr(self, "conversion_thread") and self.conversion_thread.isRunning(): if (
hasattr(self, "conversion_thread")
and self.conversion_thread.isRunning()
):
self.conversion_thread.set_timestamp_response(treat_as_subtitle) self.conversion_thread.set_timestamp_response(treat_as_subtitle)
return return
# Normal chapter detection # Normal chapter detection
from abogen.conversion import ChapterOptionsDialog from abogen.conversion import ChapterOptionsDialog
@@ -2832,7 +2838,10 @@ class abogen(QWidget):
if dialog.exec() == QDialog.DialogCode.Accepted: if dialog.exec() == QDialog.DialogCode.Accepted:
options = dialog.get_options() options = dialog.get_options()
if hasattr(self, "conversion_thread") and self.conversion_thread.isRunning(): if (
hasattr(self, "conversion_thread")
and self.conversion_thread.isRunning()
):
self.conversion_thread.set_chapter_options(options) self.conversion_thread.set_chapter_options(options)
else: else:
self.cancel_conversion() self.cancel_conversion()
@@ -3109,19 +3118,23 @@ class abogen(QWidget):
"TTS Regeneration: Better quality\n" "TTS Regeneration: Better quality\n"
"FFmpeg Time-stretch: Faster processing" "FFmpeg Time-stretch: Faster processing"
) )
speed_method_group = QActionGroup(self) speed_method_group = QActionGroup(self)
speed_method_group.setExclusive(True) speed_method_group.setExclusive(True)
for method, label in [("tts", "TTS Regeneration (better quality)"), for method, label in [
("ffmpeg", "FFmpeg Time-stretch (better speed)")]: ("tts", "TTS Regeneration (better quality)"),
("ffmpeg", "FFmpeg Time-stretch (better speed)"),
]:
action = QAction(label, speed_method_menu) action = QAction(label, speed_method_menu)
action.setCheckable(True) action.setCheckable(True)
action.setChecked(self.subtitle_speed_method == method) action.setChecked(self.subtitle_speed_method == method)
action.triggered.connect(lambda checked, m=method: self.toggle_subtitle_speed_method(m)) action.triggered.connect(
lambda checked, m=method: self.toggle_subtitle_speed_method(m)
)
speed_method_group.addAction(action) speed_method_group.addAction(action)
speed_method_menu.addAction(action) speed_method_menu.addAction(action)
self.speed_method_group = speed_method_group self.speed_method_group = speed_method_group
# Add separator # Add separator
@@ -3165,17 +3178,19 @@ class abogen(QWidget):
def toggle_use_silent_gaps(self, enabled): def toggle_use_silent_gaps(self, enabled):
# Show confirmation dialog with explanation # Show confirmation dialog with explanation
action = "enable" if enabled else "disable" action = "enable" if enabled else "disable"
message = ("When enabled, allows speech to continue naturally into the silent periods between subtitles, " message = (
"preventing unnecessary audio speed-up based on subtitle end timestamps.\n\nWhen disabled, ensures strict subtitle timing where " "When enabled, allows speech to continue naturally into the silent periods between subtitles, "
f"audio ends exactly when the subtitle ends.\n\nDo you want to {action} this option?") "preventing unnecessary audio speed-up based on subtitle end timestamps.\n\nWhen disabled, ensures strict subtitle timing where "
f"audio ends exactly when the subtitle ends.\n\nDo you want to {action} this option?"
)
reply = QMessageBox.question( reply = QMessageBox.question(
self, self,
"Use Silent Gaps Between Subtitles", "Use Silent Gaps Between Subtitles",
message, message,
QMessageBox.StandardButton.Ok | QMessageBox.StandardButton.Cancel QMessageBox.StandardButton.Ok | QMessageBox.StandardButton.Cancel,
) )
if reply == QMessageBox.StandardButton.Ok: if reply == QMessageBox.StandardButton.Ok:
self.use_silent_gaps = enabled self.use_silent_gaps = enabled
self.config["use_silent_gaps"] = enabled self.config["use_silent_gaps"] = enabled
@@ -3183,7 +3198,7 @@ class abogen(QWidget):
else: else:
# Revert the checkbox state if cancelled # Revert the checkbox state if cancelled
self.silent_gaps_action.setChecked(not enabled) self.silent_gaps_action.setChecked(not enabled)
def toggle_subtitle_speed_method(self, method): def toggle_subtitle_speed_method(self, method):
self.subtitle_speed_method = method self.subtitle_speed_method = method
self.config["subtitle_speed_method"] = method self.config["subtitle_speed_method"] = method
+7 -2
View File
@@ -8,9 +8,14 @@ import signal
if platform.system() == "Windows": if platform.system() == "Windows":
import ctypes import ctypes
from importlib.util import find_spec from importlib.util import find_spec
try: try:
if (spec := find_spec("torch")) and spec.origin and os.path.exists( if (
dll_path := os.path.join(os.path.dirname(spec.origin), "lib", "c10.dll") (spec := find_spec("torch"))
and spec.origin
and os.path.exists(
dll_path := os.path.join(os.path.dirname(spec.origin), "lib", "c10.dll")
)
): ):
ctypes.CDLL(os.path.normpath(dll_path)) ctypes.CDLL(os.path.normpath(dll_path))
except Exception: except Exception:
+18 -7
View File
@@ -88,7 +88,10 @@ class DroppableQueueListWidget(QListWidget):
if event.mimeData().hasUrls(): if event.mimeData().hasUrls():
for url in event.mimeData().urls(): for url in event.mimeData().urls():
file_path = url.toLocalFile().lower() file_path = url.toLocalFile().lower()
if url.isLocalFile() and (file_path.endswith(".txt") or file_path.endswith((".srt", ".ass", ".vtt"))): if url.isLocalFile() and (
file_path.endswith(".txt")
or file_path.endswith((".srt", ".ass", ".vtt"))
):
self.drag_overlay.resize(self.size()) self.drag_overlay.resize(self.size())
self.drag_overlay.setVisible(True) self.drag_overlay.setVisible(True)
event.acceptProposedAction() event.acceptProposedAction()
@@ -100,7 +103,10 @@ class DroppableQueueListWidget(QListWidget):
if event.mimeData().hasUrls(): if event.mimeData().hasUrls():
for url in event.mimeData().urls(): for url in event.mimeData().urls():
file_path = url.toLocalFile().lower() file_path = url.toLocalFile().lower()
if url.isLocalFile() and (file_path.endswith(".txt") or file_path.endswith((".srt", ".ass", ".vtt"))): if url.isLocalFile() and (
file_path.endswith(".txt")
or file_path.endswith((".srt", ".ass", ".vtt"))
):
event.acceptProposedAction() event.acceptProposedAction()
return return
event.ignore() event.ignore()
@@ -115,7 +121,11 @@ class DroppableQueueListWidget(QListWidget):
file_paths = [ file_paths = [
url.toLocalFile() url.toLocalFile()
for url in event.mimeData().urls() for url in event.mimeData().urls()
if url.isLocalFile() and (url.toLocalFile().lower().endswith(".txt") or url.toLocalFile().lower().endswith((".srt", ".ass", ".vtt"))) if url.isLocalFile()
and (
url.toLocalFile().lower().endswith(".txt")
or url.toLocalFile().lower().endswith((".srt", ".ass", ".vtt"))
)
] ]
if file_paths: if file_paths:
self.parent_dialog.add_files_from_paths(file_paths) self.parent_dialog.add_files_from_paths(file_paths)
@@ -408,9 +418,7 @@ class QueueManager(QDialog):
parent, "replace_single_newlines", False parent, "replace_single_newlines", False
) )
# use_silent_gaps # use_silent_gaps
attrs["use_silent_gaps"] = getattr( attrs["use_silent_gaps"] = getattr(parent, "use_silent_gaps", False)
parent, "use_silent_gaps", False
)
# subtitle_speed_method # subtitle_speed_method
attrs["subtitle_speed_method"] = getattr( attrs["subtitle_speed_method"] = getattr(
parent, "subtitle_speed_method", "tts" parent, "subtitle_speed_method", "tts"
@@ -527,7 +535,10 @@ class QueueManager(QDialog):
# Allow .txt, .srt, .ass, and .vtt files # Allow .txt, .srt, .ass, and .vtt files
files, _ = QFileDialog.getOpenFileNames( files, _ = QFileDialog.getOpenFileNames(
self, "Select text or subtitle files", "", "Supported Files (*.txt *.srt *.ass *.vtt)" self,
"Select text or subtitle files",
"",
"Supported Files (*.txt *.srt *.ass *.vtt)",
) )
if not files: if not files:
return return
+1 -1
View File
@@ -259,7 +259,7 @@ def calculate_text_length(text):
def get_gpu_acceleration(enabled): def get_gpu_acceleration(enabled):
""" """
Check GPU acceleration availability. Check GPU acceleration availability.
Note: On Windows, torch DLLs must be pre-loaded in main.py before PyQt6 Note: On Windows, torch DLLs must be pre-loaded in main.py before PyQt6
to avoid DLL initialization errors. to avoid DLL initialization errors.
""" """
+2 -2
View File
@@ -278,7 +278,7 @@ class VoiceMixer(QWidget):
# Apply slider styling once when widget is shown and has access to parent # Apply slider styling once when widget is shown and has access to parent
if not self._slider_style_applied: if not self._slider_style_applied:
self._slider_style_applied = True self._slider_style_applied = True
# Fix slider in Windows # Fix slider in Windows
if platform.system() == "Windows": if platform.system() == "Windows":
appstyle = QApplication.instance().style().objectName().lower() appstyle = QApplication.instance().style().objectName().lower()
@@ -303,7 +303,7 @@ class VoiceMixer(QWidget):
theme = parent_window.config.get("theme", "system") theme = parent_window.config.get("theme", "system")
break break
parent_window = parent_window.parent() parent_window = parent_window.parent()
if theme == "light": if theme == "light":
self.slider.setStyleSheet( self.slider.setStyleSheet(
f""" f"""