Improvements in gui and overall code

This commit is contained in:
Deniz Şafak
2025-07-10 05:12:32 +03:00
parent 742a77234f
commit 5babc936b4
3 changed files with 182 additions and 84 deletions
+102 -63
View File
@@ -738,10 +738,10 @@ class abogen(QWidget):
controls_layout.addLayout(speed_layout) controls_layout.addLayout(speed_layout)
self.speed_slider.valueChanged.connect(self.update_speed_label) self.speed_slider.valueChanged.connect(self.update_speed_label)
# Voice selection # Voice selection
voice_layout = QVBoxLayout() voice_layout = QHBoxLayout()
voice_layout.setSpacing(7) voice_layout.setSpacing(7)
voice_layout.addWidget(QLabel("Select Voice:", self)) voice_label = QLabel("Select voice:", self)
voice_row = QHBoxLayout() voice_layout.addWidget(voice_label)
self.voice_combo = QComboBox(self) self.voice_combo = QComboBox(self)
self.voice_combo.currentIndexChanged.connect(self.on_voice_combo_changed) self.voice_combo.currentIndexChanged.connect(self.on_voice_combo_changed)
self.voice_combo.setStyleSheet( self.voice_combo.setStyleSheet(
@@ -751,8 +751,8 @@ class abogen(QWidget):
"The first character represents the language:\n" "The first character represents the language:\n"
'"a" => American English\n"b" => British English\n"e" => Spanish\n"f" => French\n"h" => Hindi\n"i" => Italian\n"j" => Japanese\n"p" => Brazilian Portuguese\n"z" => Mandarin Chinese\nThe second character represents the gender:\n"m" => Male\n"f" => Female' '"a" => American English\n"b" => British English\n"e" => Spanish\n"f" => French\n"h" => Hindi\n"i" => Italian\n"j" => Japanese\n"p" => Brazilian Portuguese\n"z" => Mandarin Chinese\nThe second character represents the gender:\n"m" => Male\n"f" => Female'
) )
voice_row.addWidget(self.voice_combo) self.voice_combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
voice_layout.addWidget(self.voice_combo)
# Voice formula button # Voice formula button
self.btn_voice_formula_mixer = QPushButton(self) self.btn_voice_formula_mixer = QPushButton(self)
mixer_icon_path = get_resource_path("abogen.assets", "voice_mixer.png") mixer_icon_path = get_resource_path("abogen.assets", "voice_mixer.png")
@@ -761,8 +761,7 @@ class abogen(QWidget):
self.btn_voice_formula_mixer.setFixedSize(40, 36) self.btn_voice_formula_mixer.setFixedSize(40, 36)
self.btn_voice_formula_mixer.setStyleSheet("QPushButton { padding: 6px 12px; }") self.btn_voice_formula_mixer.setStyleSheet("QPushButton { padding: 6px 12px; }")
self.btn_voice_formula_mixer.clicked.connect(self.show_voice_formula_dialog) self.btn_voice_formula_mixer.clicked.connect(self.show_voice_formula_dialog)
voice_row.addWidget(self.btn_voice_formula_mixer) voice_layout.addWidget(self.btn_voice_formula_mixer)
# Play/Stop icons # Play/Stop icons
def make_icon(color, shape): def make_icon(color, shape):
pix = QPixmap(20, 20) pix = QPixmap(20, 20)
@@ -792,14 +791,16 @@ class abogen(QWidget):
self.btn_preview.setFixedSize(40, 36) self.btn_preview.setFixedSize(40, 36)
self.btn_preview.setStyleSheet("QPushButton { padding: 6px 12px; }") self.btn_preview.setStyleSheet("QPushButton { padding: 6px 12px; }")
self.btn_preview.clicked.connect(self.preview_voice) self.btn_preview.clicked.connect(self.preview_voice)
voice_row.addWidget(self.btn_preview) voice_layout.addWidget(self.btn_preview)
self.preview_playing = False self.preview_playing = False
self.play_audio_thread = None # Keep track of audio playing thread self.play_audio_thread = None # Keep track of audio playing thread
voice_layout.addLayout(voice_row)
controls_layout.addLayout(voice_layout) controls_layout.addLayout(voice_layout)
# Subtitle mode
subtitle_layout = QVBoxLayout() # Generate subtitles
subtitle_layout.addWidget(QLabel("Generate subtitles:", self)) subtitle_layout = QHBoxLayout()
subtitle_layout.setSpacing(7)
subtitle_label = QLabel("Generate subtitles:", self)
subtitle_layout.addWidget(subtitle_label)
self.subtitle_combo = QComboBox(self) self.subtitle_combo = QComboBox(self)
self.subtitle_combo.setToolTip( self.subtitle_combo.setToolTip(
"Choose how subtitles will be generated:\n" "Choose how subtitles will be generated:\n"
@@ -820,6 +821,7 @@ class abogen(QWidget):
self.subtitle_combo.setStyleSheet( self.subtitle_combo.setStyleSheet(
"QComboBox { min-height: 20px; padding: 6px 12px; }" "QComboBox { min-height: 20px; padding: 6px 12px; }"
) )
self.subtitle_combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.subtitle_combo.setCurrentText(self.subtitle_mode) self.subtitle_combo.setCurrentText(self.subtitle_mode)
self.subtitle_combo.currentTextChanged.connect(self.on_subtitle_mode_changed) self.subtitle_combo.currentTextChanged.connect(self.on_subtitle_mode_changed)
# Enable/disable subtitle options based on selected language (profile or voice) # Enable/disable subtitle options based on selected language (profile or voice)
@@ -827,13 +829,17 @@ class abogen(QWidget):
self.subtitle_combo.setEnabled(enable) self.subtitle_combo.setEnabled(enable)
subtitle_layout.addWidget(self.subtitle_combo) subtitle_layout.addWidget(self.subtitle_combo)
controls_layout.addLayout(subtitle_layout) controls_layout.addLayout(subtitle_layout)
# Output format
format_layout = QVBoxLayout() # Output voice format
format_layout.addWidget(QLabel("Output Format:", self)) format_layout = QHBoxLayout()
format_layout.setSpacing(7)
format_label = QLabel("Output voice format:", self)
format_layout.addWidget(format_label)
self.format_combo = QComboBox(self) self.format_combo = QComboBox(self)
self.format_combo.setStyleSheet( self.format_combo.setStyleSheet(
"QComboBox { min-height: 20px; padding: 6px 12px; }" "QComboBox { min-height: 20px; padding: 6px 12px; }"
) )
self.format_combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
# Add items with display labels and underlying keys # Add items with display labels and underlying keys
for key, label in [ for key, label in [
("wav", "wav"), ("wav", "wav"),
@@ -853,9 +859,61 @@ class abogen(QWidget):
) )
format_layout.addWidget(self.format_combo) format_layout.addWidget(self.format_combo)
controls_layout.addLayout(format_layout) controls_layout.addLayout(format_layout)
# Output subtitle format
subtitle_format_layout = QHBoxLayout()
subtitle_format_layout.setSpacing(7)
subtitle_format_label = QLabel("Output subtitle format:", self)
subtitle_format_layout.addWidget(subtitle_format_label)
self.subtitle_format_combo = QComboBox(self)
self.subtitle_format_combo.setStyleSheet(
"QComboBox { min-height: 20px; padding: 6px 12px; }"
)
self.subtitle_format_combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
subtitle_formats = [
("srt", "SRT (standard)"),
("ass_wide", "ASS (wide)"),
("ass_narrow", "ASS (narrow)"),
("ass_centered_wide", "ASS (centered wide)"),
("ass_centered_narrow", "ASS (centered narrow)")
]
for value, text in subtitle_formats:
self.subtitle_format_combo.addItem(text, value)
subtitle_format = self.config.get("subtitle_format", "ass_centered_narrow")
idx = self.subtitle_format_combo.findData(subtitle_format)
if idx >= 0:
self.subtitle_format_combo.setCurrentIndex(idx)
self.subtitle_format_combo.currentIndexChanged.connect(
lambda i: self.set_subtitle_format(self.subtitle_format_combo.itemData(i))
)
subtitle_format_layout.addWidget(self.subtitle_format_combo)
controls_layout.addLayout(subtitle_format_layout)
# Replace single newlines dropdown (acts like checkbox)
replace_newlines_layout = QHBoxLayout()
replace_newlines_layout.setSpacing(7)
replace_newlines_label = QLabel("Replace single newlines:", self)
replace_newlines_layout.addWidget(replace_newlines_label)
self.replace_newlines_combo = QComboBox(self)
self.replace_newlines_combo.addItems(["Disabled", "Enabled"])
self.replace_newlines_combo.setToolTip("Replace single newlines in the input text with spaces before processing.")
self.replace_newlines_combo.setStyleSheet(
"QComboBox { min-height: 20px; padding: 6px 12px; }"
)
self.replace_newlines_combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
# Set initial value based on config
self.replace_newlines_combo.setCurrentIndex(1 if self.replace_single_newlines else 0)
self.replace_newlines_combo.currentIndexChanged.connect(
lambda idx: self.toggle_replace_single_newlines(idx == 1)
)
replace_newlines_layout.addWidget(self.replace_newlines_combo)
controls_layout.addLayout(replace_newlines_layout)
# Save location # Save location
save_layout = QVBoxLayout() save_layout = QHBoxLayout()
save_layout.addWidget(QLabel("Save Location:", self)) save_layout.setSpacing(7)
save_label = QLabel("Save Location:", self)
save_layout.addWidget(save_label)
self.save_combo = QComboBox(self) self.save_combo = QComboBox(self)
save_options = [ save_options = [
"Save next to input file", "Save next to input file",
@@ -866,6 +924,7 @@ class abogen(QWidget):
self.save_combo.setStyleSheet( self.save_combo.setStyleSheet(
"QComboBox { min-height: 20px; padding: 6px 12px; }" "QComboBox { min-height: 20px; padding: 6px 12px; }"
) )
self.save_combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.save_combo.setCurrentText(self.save_option) self.save_combo.setCurrentText(self.save_option)
self.save_combo.currentTextChanged.connect(self.on_save_option_changed) self.save_combo.currentTextChanged.connect(self.on_save_option_changed)
save_layout.addWidget(self.save_combo) save_layout.addWidget(self.save_combo)
@@ -885,6 +944,12 @@ class abogen(QWidget):
gpu_checkbox_layout.addWidget(self.gpu_checkbox) gpu_checkbox_layout.addWidget(self.gpu_checkbox)
gpu_layout.addLayout(gpu_checkbox_layout) gpu_layout.addLayout(gpu_checkbox_layout)
# Set initial enabled state for subtitle format combo
if self.subtitle_mode == "Disabled":
self.subtitle_format_combo.setEnabled(False)
else:
self.subtitle_format_combo.setEnabled(True)
# Settings button with icon # Settings button with icon
settings_icon_path = get_resource_path("abogen.assets", "settings.svg") settings_icon_path = get_resource_path("abogen.assets", "settings.svg")
self.settings_btn = QPushButton(self) self.settings_btn = QPushButton(self)
@@ -1385,7 +1450,8 @@ class abogen(QWidget):
output_folder=self.selected_output_folder, output_folder=self.selected_output_folder,
subtitle_mode=actual_subtitle_mode, subtitle_mode=actual_subtitle_mode,
output_format=self.selected_format, output_format=self.selected_format,
total_char_count=self.char_count total_char_count=self.char_count,
replace_single_newlines=self.replace_single_newlines
) )
# Prevent adding duplicate items to the queue # Prevent adding duplicate items to the queue
@@ -1399,7 +1465,8 @@ class abogen(QWidget):
queued_item.output_folder == item.output_folder and queued_item.output_folder == item.output_folder and
queued_item.subtitle_mode == item.subtitle_mode and queued_item.subtitle_mode == item.subtitle_mode and
queued_item.output_format == item.output_format and queued_item.output_format == item.output_format and
queued_item.total_char_count == item.total_char_count queued_item.total_char_count == item.total_char_count and
getattr(queued_item, "replace_single_newlines", False) == item.replace_single_newlines
): ):
QMessageBox.warning(self, "Duplicate Item", "This item is already in the queue.") QMessageBox.warning(self, "Duplicate Item", "This item is already in the queue.")
return return
@@ -1448,6 +1515,7 @@ class abogen(QWidget):
self.subtitle_mode = item.subtitle_mode self.subtitle_mode = item.subtitle_mode
self.selected_format = item.output_format self.selected_format = item.output_format
self.char_count = item.total_char_count self.char_count = item.total_char_count
self.replace_single_newlines = getattr(item, "replace_single_newlines", False)
self.start_conversion() self.start_conversion()
else: else:
# Queue finished, reset index # Queue finished, reset index
@@ -2104,6 +2172,11 @@ class abogen(QWidget):
self.subtitle_mode = mode self.subtitle_mode = mode
self.config["subtitle_mode"] = mode self.config["subtitle_mode"] = mode
save_config(self.config) save_config(self.config)
# Disable subtitle format combo if subtitles are disabled
if mode == "Disabled":
self.subtitle_format_combo.setEnabled(False)
else:
self.subtitle_format_combo.setEnabled(True)
def on_format_changed(self, fmt): def on_format_changed(self, fmt):
self.selected_format = fmt self.selected_format = fmt
@@ -2311,45 +2384,6 @@ class abogen(QWidget):
menu.addMenu(theme_menu) menu.addMenu(theme_menu)
# Add replace single newlines option
newline_action = QAction("Replace single newlines with spaces", self)
newline_action.setCheckable(True)
newline_action.setChecked(self.replace_single_newlines)
newline_action.triggered.connect(self.toggle_replace_single_newlines)
menu.addAction(newline_action)
# Add max words per subtitle option
max_words_action = QAction("Configure max words per subtitle", self)
max_words_action.triggered.connect(self.set_max_subtitle_words)
menu.addAction(max_words_action)
# Add subtitle format option
subtitle_format_menu = QMenu("Subtitle format", self)
subtitle_format_menu.setToolTip("Choose the format for generated subtitles")
subtitle_format_group = QActionGroup(self)
subtitle_format_group.setExclusive(True)
# Define mapping: (internal_value, display_text)
subtitle_formats = [
("srt", "SRT (standard)"),
("ass_wide", "ASS (wide)"),
("ass_narrow", "ASS (narrow)"),
("ass_centered_wide", "ASS (centered wide)"),
("ass_centered_narrow", "ASS (centered narrow)"),
]
subtitle_format = self.config.get("subtitle_format", "ass_centered_narrow")
for value, text in subtitle_formats:
format_action = QAction(text, self)
format_action.setCheckable(True)
format_action.setChecked(subtitle_format == value)
format_action.triggered.connect(lambda checked, fmt=value: self.set_subtitle_format(fmt))
subtitle_format_group.addAction(format_action)
subtitle_format_menu.addAction(format_action)
menu.addMenu(subtitle_format_menu)
# Add separate chapters format option # Add separate chapters format option
separate_chapters_format_menu = QMenu("Separate chapters audio format", self) separate_chapters_format_menu = QMenu("Separate chapters audio format", self)
separate_chapters_format_menu.setToolTip("Choose the format for individual chapter files") separate_chapters_format_menu.setToolTip("Choose the format for individual chapter files")
@@ -2367,6 +2401,13 @@ class abogen(QWidget):
menu.addMenu(separate_chapters_format_menu) menu.addMenu(separate_chapters_format_menu)
# Add max words per subtitle option
max_words_action = QAction("Configure max words per subtitle", self)
max_words_action.triggered.connect(self.set_max_subtitle_words)
menu.addAction(max_words_action)
# Add separator # Add separator
menu.addSeparator() menu.addSeparator()
@@ -2410,9 +2451,9 @@ class abogen(QWidget):
menu.exec_(self.settings_btn.mapToGlobal(QPoint(0, self.settings_btn.height()))) menu.exec_(self.settings_btn.mapToGlobal(QPoint(0, self.settings_btn.height())))
def toggle_replace_single_newlines(self, checked): def toggle_replace_single_newlines(self, enabled):
self.replace_single_newlines = checked self.replace_single_newlines = enabled
self.config["replace_single_newlines"] = checked self.config["replace_single_newlines"] = enabled
save_config(self.config) save_config(self.config)
def reveal_config_in_explorer(self): def reveal_config_in_explorer(self):
@@ -2609,8 +2650,6 @@ Categories=AudioVideo;Audio;Utility;
initial_state = entry initial_state = entry
else: else:
initial_state = [] initial_state = []
else:
initial_state = []
dialog = VoiceFormulaDialog( dialog = VoiceFormulaDialog(
self, initial_state=initial_state, selected_profile=selected_profile self, initial_state=initial_state, selected_profile=selected_profile
) )
+77 -19
View File
@@ -15,11 +15,13 @@ from PyQt5.QtWidgets import (
) )
from PyQt5.QtCore import QFileInfo, Qt from PyQt5.QtCore import QFileInfo, Qt
from constants import COLORS from constants import COLORS
from copy import deepcopy
class QueueManager(QDialog): class QueueManager(QDialog):
def __init__(self, parent, queue: list, title="Queue Manager", size=(600, 700)): def __init__(self, parent, queue: list, title="Queue Manager", size=(600, 700)):
super().__init__() super().__init__()
self.queue = queue self.queue = queue
self._original_queue = deepcopy(queue) # Store a deep copy of the original queue
self.parent = parent self.parent = parent
layout = QVBoxLayout() layout = QVBoxLayout()
layout.setContentsMargins(15, 15, 15, 15) # set main layout margins layout.setContentsMargins(15, 15, 15, 15) # set main layout margins
@@ -131,7 +133,8 @@ class QueueManager(QDialog):
tooltip += ( tooltip += (
f"<b>Subtitle Mode:</b> {getattr(item, 'subtitle_mode', '')}<br>" f"<b>Subtitle Mode:</b> {getattr(item, 'subtitle_mode', '')}<br>"
f"<b>Output Format:</b> {getattr(item, 'output_format', '')}<br>" f"<b>Output Format:</b> {getattr(item, 'output_format', '')}<br>"
f"<b>Characters:</b> {getattr(item, 'total_char_count', '')}" f"<b>Characters:</b> {getattr(item, 'total_char_count', '')}<br>"
f"<b>Replace Single Newlines:</b> {getattr(item, 'replace_single_newlines', False)}"
) )
list_item.setToolTip(tooltip) list_item.setToolTip(tooltip)
self.listwidget.addItem(list_item) self.listwidget.addItem(list_item)
@@ -143,11 +146,23 @@ class QueueManager(QDialog):
if not items: if not items:
return return
import os import os
from PyQt5.QtWidgets import QMessageBox
display_names = [item.text() for item in items] display_names = [item.text() for item in items]
to_remove = [] to_remove = []
for q in self.queue: for q in self.queue:
if os.path.basename(q.file_name) in display_names: if os.path.basename(q.file_name) in display_names:
to_remove.append(q) to_remove.append(q)
# Warn user if removing multiple files
if len(to_remove) > 1:
reply = QMessageBox.question(
self,
"Confirm Remove",
f"Are you sure you want to remove {len(to_remove)} selected items from the queue?",
QMessageBox.Yes | QMessageBox.No,
QMessageBox.No
)
if reply != QMessageBox.Yes:
return
for item in to_remove: for item in to_remove:
self.queue.remove(item) self.queue.remove(item)
self.process_queue() self.process_queue()
@@ -205,11 +220,13 @@ class QueueManager(QDialog):
attrs['output_format'] = getattr(parent, 'selected_format', '') attrs['output_format'] = getattr(parent, 'selected_format', '')
# total_char_count # total_char_count
attrs['total_char_count'] = getattr(parent, 'char_count', '') attrs['total_char_count'] = getattr(parent, 'char_count', '')
# replace_single_newlines
attrs['replace_single_newlines'] = getattr(parent, 'replace_single_newlines', False)
else: else:
# fallback: empty values # fallback: empty values
attrs = {k: '' for k in [ attrs = {k: '' for k in [
'lang_code', 'speed', 'voice', 'save_option', 'lang_code', 'speed', 'voice', 'save_option',
'output_folder', 'subtitle_mode', 'output_format', 'total_char_count']} 'output_folder', 'subtitle_mode', 'output_format', 'total_char_count', 'replace_single_newlines']}
return attrs return attrs
def add_more_files(self): def add_more_files(self):
@@ -250,7 +267,8 @@ class QueueManager(QDialog):
getattr(queued_item, 'output_folder', None) == getattr(item, 'output_folder', None) and getattr(queued_item, 'output_folder', None) == getattr(item, 'output_folder', None) and
getattr(queued_item, 'subtitle_mode', None) == getattr(item, 'subtitle_mode', None) and getattr(queued_item, 'subtitle_mode', None) == getattr(item, 'subtitle_mode', None) and
getattr(queued_item, 'output_format', None) == getattr(item, 'output_format', None) and getattr(queued_item, 'output_format', None) == getattr(item, 'output_format', None) and
getattr(queued_item, 'total_char_count', None) == getattr(item, 'total_char_count', None) getattr(queued_item, 'total_char_count', None) == getattr(item, 'total_char_count', None) and
getattr(queued_item, 'replace_single_newlines', False) == getattr(item, 'replace_single_newlines', False)
): ):
is_duplicate = True is_duplicate = True
break break
@@ -259,7 +277,11 @@ class QueueManager(QDialog):
continue continue
self.queue.append(item) self.queue.append(item)
if duplicates: if duplicates:
QMessageBox.warning(self, "Duplicate Item(s)", "The following file(s) with the same attributes are already in the queue and were not added:\n" + '\n'.join(duplicates)) QMessageBox.warning(
self,
"Duplicate Item(s)",
f"Skipping {len(duplicates)} file(s) with the same attributes, they are already in the queue."
)
self.process_queue() self.process_queue()
self.update_button_states() self.update_button_states()
@@ -290,9 +312,28 @@ class QueueManager(QDialog):
selected_items = self.listwidget.selectedItems() selected_items = self.listwidget.selectedItems()
menu = QMenu(self) menu = QMenu(self)
if len(selected_items) == 1: if len(selected_items) == 1:
# Add Remove action
remove_action = QAction("Remove this item", self) remove_action = QAction("Remove this item", self)
remove_action.triggered.connect(self.remove_item) remove_action.triggered.connect(self.remove_item)
menu.addAction(remove_action) menu.addAction(remove_action)
# Add Open file action
open_file_action = QAction("Open file", self)
def open_file():
from PyQt5.QtWidgets import QMessageBox
item = selected_items[0]
display_name = item.text()
for q in self.queue:
if os.path.basename(q.file_name) == display_name:
if not os.path.exists(q.file_name):
QMessageBox.warning(self, "File Not Found", f"The file does not exist.")
return
QDesktopServices.openUrl(QUrl.fromLocalFile(q.file_name))
break
open_file_action.triggered.connect(open_file)
menu.addAction(open_file_action)
# Add Go to folder action
go_to_folder_action = QAction("Go to folder", self) go_to_folder_action = QAction("Go to folder", self)
def go_to_folder(): def go_to_folder():
from PyQt5.QtWidgets import QMessageBox from PyQt5.QtWidgets import QMessageBox
@@ -309,21 +350,7 @@ class QueueManager(QDialog):
break break
go_to_folder_action.triggered.connect(go_to_folder) go_to_folder_action.triggered.connect(go_to_folder)
menu.addAction(go_to_folder_action) menu.addAction(go_to_folder_action)
# Add Open file action
open_file_action = QAction("Open file", self)
def open_file():
from PyQt5.QtWidgets import QMessageBox
item = selected_items[0]
display_name = item.text()
for q in self.queue:
if os.path.basename(q.file_name) == display_name:
if not os.path.exists(q.file_name):
QMessageBox.warning(self, "File Not Found", f"The file does not exist.")
return
QDesktopServices.openUrl(QUrl.fromLocalFile(q.file_name))
break
open_file_action.triggered.connect(open_file)
menu.addAction(open_file_action)
elif len(selected_items) > 1: elif len(selected_items) > 1:
remove_action = QAction(f"Remove selected ({len(selected_items)})", self) remove_action = QAction(f"Remove selected ({len(selected_items)})", self)
remove_action.triggered.connect(self.remove_item) remove_action.triggered.connect(self.remove_item)
@@ -333,3 +360,34 @@ class QueueManager(QDialog):
clear_action.triggered.connect(self.clear_queue) clear_action.triggered.connect(self.clear_queue)
menu.addAction(clear_action) menu.addAction(clear_action)
menu.exec_(global_pos) menu.exec_(global_pos)
def accept(self):
# Accept: keep changes
super().accept()
def reject(self):
# Cancel: restore original queue
from PyQt5.QtWidgets import QMessageBox
# Warn if user changed a lot (e.g., more than 1 items difference)
original_count = len(self._original_queue)
current_count = len(self.queue)
if abs(original_count - current_count) > 1:
reply = QMessageBox.question(
self,
"Confirm Cancel",
f"Are you sure you want to cancel and discard all changes?",
QMessageBox.Yes | QMessageBox.No,
QMessageBox.No
)
if reply != QMessageBox.Yes:
return
self.queue.clear()
self.queue.extend(deepcopy(self._original_queue))
super().reject()
def keyPressEvent(self, event):
from PyQt5.QtCore import Qt
if event.key() == Qt.Key_Delete:
self.remove_item()
else:
super().keyPressEvent(event)
+1
View File
@@ -12,3 +12,4 @@ class QueuedItem:
subtitle_mode: str subtitle_mode: str
output_format: str output_format: str
total_char_count: int total_char_count: int
replace_single_newlines: bool = False