9 Commits
11 changed files with 683 additions and 591 deletions
+11
View File
@@ -1,3 +1,14 @@
# v1.1.2
- Now you can play the audio files while they are processing.
- Audio and subtitle files are now written directly to disk during generation, which significantly reduces memory usage.
- Added a better logic for detecting chapters from the epub, mentioned by @jefro108 in #33
- Added a new option: `Reset to default settings`, allowing users to reset all settings to their default values.
- Added a new option: `Disable Kokoro's internet access`. This lets you prevent Kokoro from downloading models or voices from HuggingFace Hub, which can help avoid long waiting times if your computer is offline.
- HuggingFace Hub telemetry is now disabled by default for improved privacy. (HuggingFace Hub is used by Kokoro to download its models)
- Potential fix for #37 and #38, where the program was becoming slow while processing large files.
- Fixed `Open folder` and `Open file` buttons in the queue manager GUI.
- Improvements in code structure.
# v1.1.1 # v1.1.1
- Fixed adding wrong file in queue for EPUB and PDF files, ensuring the correct file is added to the queue. - Fixed adding wrong file in queue for EPUB and PDF files, ensuring the correct file is added to the queue.
- Reformatted the code using Black. - Reformatted the code using Black.
+2
View File
@@ -153,6 +153,8 @@ Heres Abogen in action: in this demo, it processes 3,000 characters of tex
| **Open temp directory** | Opens the temporary directory where converted text files are stored. | | **Open temp directory** | Opens the temporary directory where converted text files are stored. |
| **Clear temporary files** | Deletes temporary files created during the conversion or preview. | | **Clear temporary files** | Deletes temporary files created during the conversion or preview. |
| **Check for updates at startup** | Automatically checks for updates when the program starts. | | **Check for updates at startup** | Automatically checks for updates when the program starts. |
| **Disable Kokoro's internet access** | Prevents Kokoro from downloading models or voices from HuggingFace Hub, useful for offline use. |
| **Reset to default settings** | Resets all settings to their default values. |
## `Voice Mixer` ## `Voice Mixer`
<img title="Abogen Voice Mixer" src='https://raw.githubusercontent.com/denizsafak/abogen/refs/heads/main/demo/voice_mixer.png'> <img title="Abogen Voice Mixer" src='https://raw.githubusercontent.com/denizsafak/abogen/refs/heads/main/demo/voice_mixer.png'>
+2 -2
View File
@@ -230,7 +230,7 @@ if errorlevel 1 (
:: Install setup requirements :: Install setup requirements
echo Installing setup requirements... echo Installing setup requirements...
%PYTHON_CONSOLE_PATH% -m pip install --upgrade setuptools setuptools-scm wheel sphinx hatchling --no-warn-script-location %PYTHON_CONSOLE_PATH% -m pip install --upgrade setuptools setuptools-scm wheel sphinx hatchling editables --no-warn-script-location
if errorlevel 1 ( if errorlevel 1 (
echo Failed to install setup requirements. echo Failed to install setup requirements.
pause pause
@@ -250,7 +250,7 @@ if errorlevel 1 (
echo Checking and installing project dependencies... echo Checking and installing project dependencies...
if exist %PYPROJECT_FILE% ( if exist %PYPROJECT_FILE% (
echo Installing project from pyproject.toml... echo Installing project from pyproject.toml...
%PYTHON_CONSOLE_PATH% -m pip install . --no-warn-script-location %PYTHON_CONSOLE_PATH% -m pip install -e . --no-warn-script-location
if errorlevel 1 ( if errorlevel 1 (
echo Failed to install from pyproject.toml. echo Failed to install from pyproject.toml.
pause pause
+1 -1
View File
@@ -1 +1 @@
1.1.1 1.1.2
+17 -12
View File
@@ -22,7 +22,7 @@ from PyQt5.QtWidgets import (
QLabel, QLabel,
) )
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from utils import clean_text, calculate_text_length from abogen.utils import clean_text, calculate_text_length
import os import os
import logging # Add logging import logging # Add logging
import urllib.parse import urllib.parse
@@ -240,20 +240,17 @@ class HandlerDialog(QDialog):
tag.decompose() tag.decompose()
text = clean_text(soup.get_text()).strip() text = clean_text(soup.get_text()).strip()
if text: if text:
# Use doc_href as the identifier
self.content_texts[doc_href] = text self.content_texts[doc_href] = text
self.content_lengths[doc_href] = len(text) self.content_lengths[doc_href] = len(text)
# Create a synthetic TOC entry
title = f"Chapter {i+1}: {doc_href}"
# Try to get a better title from <h1> or <title>
h1 = soup.find("h1")
if h1 and h1.get_text(strip=True):
title = h1.get_text(strip=True)
else:
title_tag = soup.find("title")
if title_tag and title_tag.get_text(strip=True):
title = title_tag.get_text(strip=True)
title = None
if soup.title and soup.title.string:
title = soup.title.string.strip()
elif (h1 := soup.find("h1")) and h1.get_text(strip=True):
title = h1.get_text(strip=True)
if not title:
title = f"Untitled Chapter {i+1}"
synthetic_toc.append( synthetic_toc.append(
(epub.Link(doc_href, title, doc_href), []) (epub.Link(doc_href, title, doc_href), [])
) # Wrap in tuple and empty list for compatibility ) # Wrap in tuple and empty list for compatibility
@@ -1911,5 +1908,13 @@ class HandlerDialog(QDialog):
def closeEvent(self, event): def closeEvent(self, event):
if self.pdf_doc is not None: if self.pdf_doc is not None:
try:
if hasattr(self.pdf_doc, "is_closed"):
if not self.pdf_doc.is_closed:
self.pdf_doc.close() self.pdf_doc.close()
else:
# Fallback: try/except close
self.pdf_doc.close()
except Exception:
pass
event.accept() event.accept()
+8
View File
@@ -10,6 +10,13 @@ VERSION = get_version()
# Settings # Settings
CHAPTER_OPTIONS_COUNTDOWN = 30 # Countdown seconds for chapter options CHAPTER_OPTIONS_COUNTDOWN = 30 # Countdown seconds for chapter options
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)"),
]
# Language description mapping # Language description mapping
LANGUAGE_DESCRIPTIONS = { LANGUAGE_DESCRIPTIONS = {
@@ -109,6 +116,7 @@ SAMPLE_VOICE_TEXTS = {
COLORS = { COLORS = {
"BLUE": "#007dff", "BLUE": "#007dff",
"RED": "#c0392b", "RED": "#c0392b",
"ORANGE": "#FFA500",
"GREEN": "#42ad4a", "GREEN": "#42ad4a",
"GREEN_BG": "rgba(66, 173, 73, 0.1)", "GREEN_BG": "rgba(66, 173, 73, 0.1)",
"GREEN_BG_HOVER": "rgba(66, 173, 73, 0.15)", "GREEN_BG_HOVER": "rgba(66, 173, 73, 0.15)",
+446 -466
View File
File diff suppressed because it is too large Load Diff
+124 -49
View File
@@ -75,6 +75,7 @@ from abogen.constants import (
VOICES_INTERNAL, VOICES_INTERNAL,
SUPPORTED_LANGUAGES_FOR_SUBTITLE_GENERATION, SUPPORTED_LANGUAGES_FOR_SUBTITLE_GENERATION,
COLORS, COLORS,
SUBTITLE_FORMATS,
) )
import threading import threading
from abogen.voice_formula_gui import VoiceFormulaDialog from abogen.voice_formula_gui import VoiceFormulaDialog
@@ -124,6 +125,18 @@ class IconProvider(QFileIconProvider):
return super().icon(fileInfo) return super().icon(fileInfo)
LOG_COLOR_MAP = {
True: COLORS["GREEN"],
False: COLORS["RED"],
"red": COLORS["RED"],
"green": COLORS["GREEN"],
"orange": COLORS["ORANGE"],
"blue": COLORS["BLUE"],
"grey": COLORS["LIGHT_DISABLED"],
None: COLORS["LIGHT_DISABLED"],
}
class InputBox(QLabel): class InputBox(QLabel):
# Define CSS styles as class constants # Define CSS styles as class constants
STYLE_DEFAULT = f"border:2px dashed #aaa; border-radius:5px; padding:20px; background:{COLORS['BLUE_BG']}; min-height:100px;" STYLE_DEFAULT = f"border:2px dashed #aaa; border-radius:5px; padding:20px; background:{COLORS['BLUE_BG']}; min-height:100px;"
@@ -646,7 +659,7 @@ class abogen(QWidget):
None # Add new variable to track the displayed file path None # Add new variable to track the displayed file path
) )
# Max log lines # Max log lines
self.log_window_max_lines = self.config.get("log_window_max_lines", 5000) self.log_window_max_lines = self.config.get("log_window_max_lines", 2000)
self.selected_chapters = set() self.selected_chapters = set()
self.last_opened_book_path = None # Track the last opened book path self.last_opened_book_path = None # Track the last opened book path
self.last_output_path = None self.last_output_path = None
@@ -700,9 +713,6 @@ class abogen(QWidget):
self.queued_items = [] self.queued_items = []
self.current_queue_index = 0 self.current_queue_index = 0
# Log lines
self._log_lines = []
self.initUI() self.initUI()
self.speed_slider.setValue(int(self.config.get("speed", 1.00) * 100)) self.speed_slider.setValue(int(self.config.get("speed", 1.00) * 100))
self.update_speed_label() self.update_speed_label()
@@ -785,6 +795,7 @@ class abogen(QWidget):
container_layout.addWidget(self.queue_row_widget) container_layout.addWidget(self.queue_row_widget)
self.log_text = QTextEdit(self) self.log_text = QTextEdit(self)
self.log_text.setReadOnly(True) self.log_text.setReadOnly(True)
self.log_text.setUndoRedoEnabled(False)
self.log_text.setFrameStyle(QTextEdit.NoFrame) self.log_text.setFrameStyle(QTextEdit.NoFrame)
self.log_text.setStyleSheet("QTextEdit { border: none; }") self.log_text.setStyleSheet("QTextEdit { border: none; }")
self.log_text.hide() self.log_text.hide()
@@ -944,14 +955,7 @@ class abogen(QWidget):
self.subtitle_format_combo.setSizePolicy( self.subtitle_format_combo.setSizePolicy(
QSizePolicy.Expanding, QSizePolicy.Fixed QSizePolicy.Expanding, QSizePolicy.Fixed
) )
subtitle_formats = [ for value, text in 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) self.subtitle_format_combo.addItem(text, value)
subtitle_format = self.config.get("subtitle_format", "ass_centered_narrow") subtitle_format = self.config.get("subtitle_format", "ass_centered_narrow")
idx = self.subtitle_format_combo.findData(subtitle_format) idx = self.subtitle_format_combo.findData(subtitle_format)
@@ -1458,16 +1462,12 @@ class abogen(QWidget):
self.input_box.hide() self.input_box.hide()
self.log_text.show() self.log_text.show()
self.log_text.clear() self.log_text.clear()
self._log_lines = []
QApplication.processEvents() QApplication.processEvents()
def restore_input_box(self): def restore_input_box(self):
self.log_text.hide() self.log_text.hide()
self.input_box.show() self.input_box.show()
def color_text(self, message, color):
return f'<span style="color:{color};">{message.replace(chr(10), "<br>")}</span><br>'
def update_log(self, message): def update_log(self, message):
# Use signal-based approach for thread-safe logging # Use signal-based approach for thread-safe logging
if QThread.currentThread() != QApplication.instance().thread(): if QThread.currentThread() != QApplication.instance().thread():
@@ -1479,38 +1479,36 @@ class abogen(QWidget):
self._update_log_main_thread(message) self._update_log_main_thread(message)
def _update_log_main_thread(self, message): def _update_log_main_thread(self, message):
if not hasattr(self, "_log_lines"): txt = self.log_text
self._log_lines = [] sb = txt.verticalScrollBar()
at_bottom = sb.value() == sb.maximum()
# Always produce a single HTML line (with color if tuple) cursor = txt.textCursor()
cursor.movePosition(QTextCursor.End)
fmt = cursor.charFormat()
if isinstance(message, tuple): if isinstance(message, tuple):
text, spec = message text, spec = message
color = "green" if spec is True else ("red" if spec is False else spec) fmt.setForeground(QColor(LOG_COLOR_MAP.get(spec, COLORS["LIGHT_DISABLED"])))
html_line = self.color_text(text, color)
else: else:
html_line = f"{str(message).replace(chr(10), '<br>')}<br>" text = str(message)
fmt.clearForeground()
cursor.setCharFormat(fmt)
cursor.insertText(text + "\n")
self._log_lines.append(html_line) doc = txt.document()
excess = doc.blockCount() - self.log_window_max_lines
if excess > 0:
start = doc.findBlockByNumber(0).position()
end = doc.findBlockByNumber(excess).position()
trim_cursor = QTextCursor(doc)
trim_cursor.setPosition(start)
trim_cursor.setPosition(end, QTextCursor.KeepAnchor)
trim_cursor.removeSelectedText()
# Check if user is at bottom BEFORE inserting
sb = self.log_text.verticalScrollBar()
at_bottom = sb.value() >= sb.maximum() - 2
# Trim buffer if needed
if len(self._log_lines) > self.log_window_max_lines:
self._log_lines = self._log_lines[-self.log_window_max_lines :]
self.log_text.clear()
for line in self._log_lines:
self.log_text.insertHtml(line)
else:
self.log_text.insertHtml(html_line)
# If user was at bottom before, scroll to new bottom
if at_bottom: if at_bottom:
sb.setValue(sb.maximum()) sb.setValue(sb.maximum())
QApplication.processEvents()
def _get_queue_progress_format(self, value=None): def _get_queue_progress_format(self, value=None):
"""Return the progress bar format string for queue mode.""" """Return the progress bar format string for queue mode."""
if ( if (
@@ -1889,7 +1887,7 @@ class abogen(QWidget):
f"<span style='color:{COLORS['GREEN']}; font-weight:bold;'>{idx}) {os.path.basename(item.file_name)}</span><br>" f"<span style='color:{COLORS['GREEN']}; font-weight:bold;'>{idx}) {os.path.basename(item.file_name)}</span><br>"
f"<span style='color:{COLORS['LIGHT_DISABLED']};'>Language:</span> {item.lang_code}<br>" f"<span style='color:{COLORS['LIGHT_DISABLED']};'>Language:</span> {item.lang_code}<br>"
f"<span style='color:{COLORS['LIGHT_DISABLED']};'>Voice:</span> {item.voice}<br>" f"<span style='color:{COLORS['LIGHT_DISABLED']};'>Voice:</span> {item.voice}<br>"
f"<span style='color:{COLORS['LIGHT_DISABLED']};'>Speed:</span> {item.speed * 100:.1f}%<br>" f"<span style='color:{COLORS['LIGHT_DISABLED']};'>Speed:</span> {item.speed}<br>"
f"<span style='color:{COLORS['LIGHT_DISABLED']};'>Characters:</span> {item.total_char_count}<br>" f"<span style='color:{COLORS['LIGHT_DISABLED']};'>Characters:</span> {item.total_char_count}<br>"
f"<span style='color:{COLORS['LIGHT_DISABLED']};'>Input:</span> {item.file_name}<br>" f"<span style='color:{COLORS['LIGHT_DISABLED']};'>Input:</span> {item.file_name}<br>"
f"<span style='color:{COLORS['LIGHT_DISABLED']};'>Output:</span> {output}</span>" f"<span style='color:{COLORS['LIGHT_DISABLED']};'>Output:</span> {output}</span>"
@@ -1988,7 +1986,6 @@ class abogen(QWidget):
else: else:
# More items in queue: clear log and reload for next item # More items in queue: clear log and reload for next item
self.log_text.clear() self.log_text.clear()
self._log_lines = []
QApplication.processEvents() QApplication.processEvents()
# Start new queued item, if we're using a queued conversion # Start new queued item, if we're using a queued conversion
@@ -2032,7 +2029,6 @@ class abogen(QWidget):
self.progress_bar.hide() self.progress_bar.hide()
self.restore_input_box() self.restore_input_box()
self.log_text.clear() self.log_text.clear()
self._log_lines = []
# Use displayed_file_path instead of selected_file for EPUBs or PDFs # Use displayed_file_path instead of selected_file for EPUBs or PDFs
display_path = ( display_path = (
@@ -2444,7 +2440,6 @@ class abogen(QWidget):
self.finish_widget.hide() self.finish_widget.hide()
self.restore_input_box() self.restore_input_box()
self.log_text.clear() self.log_text.clear()
self._log_lines = []
display_path = ( display_path = (
self.displayed_file_path self.displayed_file_path
if self.displayed_file_path if self.displayed_file_path
@@ -2484,6 +2479,16 @@ class abogen(QWidget):
self.config["use_gpu"] = self.use_gpu self.config["use_gpu"] = self.use_gpu
save_config(self.config) save_config(self.config)
def cleanup_conversion_thread(self):
# Stop conversion thread
if (
hasattr(self, "conversion_thread")
and self.conversion_thread is not None
and self.conversion_thread.isRunning()
):
self.conversion_thread.cancel()
self.conversion_thread.wait()
def closeEvent(self, event): def closeEvent(self, event):
if self.is_converting: if self.is_converting:
box = QMessageBox(self) box = QMessageBox(self)
@@ -2495,16 +2500,12 @@ class abogen(QWidget):
box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
box.setDefaultButton(QMessageBox.No) box.setDefaultButton(QMessageBox.No)
if box.exec_() == QMessageBox.Yes: if box.exec_() == QMessageBox.Yes:
if ( self.cleanup_conversion_thread()
hasattr(self, "conversion_thread")
and self.conversion_thread.isRunning()
):
self.conversion_thread.cancel()
self.conversion_thread.wait()
event.accept() event.accept()
else: else:
event.ignore() event.ignore()
else: else:
self.cleanup_conversion_thread()
event.accept() event.accept()
def show_chapter_options_dialog(self, chapter_count): def show_chapter_options_dialog(self, chapter_count):
@@ -2779,6 +2780,17 @@ class abogen(QWidget):
# Add seperator" # Add seperator"
menu.addSeparator() menu.addSeparator()
# Add "Disable Kokoro's internet access" option
disable_kokoro_action = QAction("Disable Kokoro's internet access", self)
disable_kokoro_action.setCheckable(True)
disable_kokoro_action.setChecked(
self.config.get("disable_kokoro_internet", False)
)
disable_kokoro_action.triggered.connect(
lambda checked: self.toggle_kokoro_internet_access(checked)
)
menu.addAction(disable_kokoro_action)
# Add check for updates option # Add check for updates option
check_updates_action = QAction("Check for updates at startup", self) check_updates_action = QAction("Check for updates at startup", self)
check_updates_action.setCheckable(True) check_updates_action.setCheckable(True)
@@ -2786,6 +2798,11 @@ class abogen(QWidget):
check_updates_action.triggered.connect(self.toggle_check_updates) check_updates_action.triggered.connect(self.toggle_check_updates)
menu.addAction(check_updates_action) menu.addAction(check_updates_action)
# Add "Reset to default settings" option
reset_defaults_action = QAction("Reset to default settings", self)
reset_defaults_action.triggered.connect(self.reset_to_default_settings)
menu.addAction(reset_defaults_action)
# Add about action # Add about action
about_action = QAction("About", self) about_action = QAction("About", self)
about_action.triggered.connect(self.show_about_dialog) about_action.triggered.connect(self.show_about_dialog)
@@ -2798,6 +2815,64 @@ class abogen(QWidget):
self.config["replace_single_newlines"] = enabled self.config["replace_single_newlines"] = enabled
save_config(self.config) save_config(self.config)
def toggle_kokoro_internet_access(self, disabled):
if disabled:
message = (
"Disabling Kokoro's internet access will block downloads of models and voices from Hugging Face Hub. "
"This can make processing faster when there is no internet connection, since no requests will be made. "
"The app needs to restart to apply this change.\n\nDo you want to continue?"
)
else:
message = (
"Enabling Kokoro's internet access will allow it to download models and voices from Hugging Face Hub. "
"The app needs to restart to apply this change.\n\nDo you want to continue?"
)
reply = QMessageBox.question(
self,
"Restart Required",
message,
QMessageBox.Yes | QMessageBox.No,
QMessageBox.No,
)
if reply == QMessageBox.Yes:
self.config["disable_kokoro_internet"] = disabled
save_config(self.config)
try:
from PyQt5.QtCore import QProcess
import sys
QProcess.startDetached(sys.executable, sys.argv)
QApplication.quit()
except Exception as e:
QMessageBox.critical(
self, "Restart Failed", f"Failed to restart the application:\n{e}"
)
def reset_to_default_settings(self):
reply = QMessageBox.question(
self,
"Reset Settings",
"This will reset all settings to their default values and restart the application.\n\nDo you want to continue?",
QMessageBox.Yes | QMessageBox.No,
QMessageBox.No,
)
if reply == QMessageBox.Yes:
from abogen.utils import get_user_config_path
import sys
config_path = get_user_config_path()
try:
if os.path.exists(config_path):
os.remove(config_path)
from PyQt5.QtCore import QProcess
QProcess.startDetached(sys.executable, sys.argv)
QApplication.quit()
except Exception as e:
QMessageBox.critical(
self, "Reset Error", f"Could not reset settings:\n{e}"
)
def reveal_config_in_explorer(self): def reveal_config_in_explorer(self):
"""Open the configuration file location in file explorer.""" """Open the configuration file location in file explorer."""
from abogen.utils import get_user_config_path from abogen.utils import get_user_config_path
+13 -1
View File
@@ -1,3 +1,4 @@
from json import load
import os import os
import sys import sys
import platform import platform
@@ -7,8 +8,19 @@ from PyQt5.QtCore import qInstallMessageHandler, QtMsgType
# Add the directory to Python path # Add the directory to Python path
sys.path.insert(0, os.path.join(os.path.dirname(__file__))) sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
from abogen.utils import get_resource_path, load_config
# Set Hugging Face Hub environment variables
os.environ["HF_HUB_DISABLE_TELEMETRY"] = "1" # Disable Hugging Face telemetry
os.environ["HF_HUB_ETAG_TIMEOUT"] = "10" # Metadata request timeout (seconds)
os.environ["HF_HUB_DOWNLOAD_TIMEOUT"] = "10" # File download timeout (seconds)
os.environ["HF_HUB_DISABLE_SYMLINKS_WARNING"] = "1" # Disable symlinks warning
if load_config().get("disable_kokoro_internet", False):
print("INFO: Kokoro's internet access is disabled.")
os.environ["HF_HUB_OFFLINE"] = "1" # Disable Hugging Face Hub internet access
from abogen.gui import abogen from abogen.gui import abogen
from abogen.utils import get_resource_path
from abogen.constants import PROGRAM_NAME, VERSION from abogen.constants import PROGRAM_NAME, VERSION
# Set environment variables for AMD ROCm # Set environment variables for AMD ROCm
+5 -4
View File
@@ -246,6 +246,7 @@ class QueueManager(QDialog):
) )
list_item.setToolTip(tooltip) list_item.setToolTip(tooltip)
list_item.setIcon(icon) list_item.setIcon(icon)
list_item.setData(Qt.UserRole, file_name)
# Use custom widget for display # Use custom widget for display
char_count = getattr(item, "total_char_count", 0) char_count = getattr(item, "total_char_count", 0)
widget = QueueListItemWidget(file_name, char_count) widget = QueueListItemWidget(file_name, char_count)
@@ -472,9 +473,9 @@ class QueueManager(QDialog):
from PyQt5.QtWidgets import QMessageBox from PyQt5.QtWidgets import QMessageBox
item = selected_items[0] item = selected_items[0]
display_name = item.text() file_path = item.data(Qt.UserRole)
for q in self.queue: for q in self.queue:
if os.path.basename(q.file_name) == display_name: if q.file_name == file_path:
if not os.path.exists(q.file_name): if not os.path.exists(q.file_name):
QMessageBox.warning( QMessageBox.warning(
self, "File Not Found", f"The file does not exist." self, "File Not Found", f"The file does not exist."
@@ -493,9 +494,9 @@ class QueueManager(QDialog):
from PyQt5.QtWidgets import QMessageBox from PyQt5.QtWidgets import QMessageBox
item = selected_items[0] item = selected_items[0]
display_name = item.text() file_path = item.data(Qt.UserRole)
for q in self.queue: for q in self.queue:
if os.path.basename(q.file_name) == display_name: if q.file_name == file_path:
if not os.path.exists(q.file_name): if not os.path.exists(q.file_name):
QMessageBox.warning( QMessageBox.warning(
self, "File Not Found", f"The file does not exist." self, "File Not Found", f"The file does not exist."
-2
View File
@@ -7,8 +7,6 @@ import subprocess
import re import re
from threading import Thread from threading import Thread
# suppress warnings and disable HF hub symlink warnings
os.environ["HF_HUB_DISABLE_SYMLINKS_WARNING"] = "1"
warnings.filterwarnings("ignore") warnings.filterwarnings("ignore")