mirror of
https://github.com/denizsafak/abogen.git
synced 2026-07-18 21:50:28 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0195788a54 | ||
|
|
1fd8fe21b7 | ||
|
|
89a7116c87 | ||
|
|
6b85a08ccb | ||
|
|
b9c3fd7c6c | ||
|
|
a35bea9053 | ||
|
|
e2802a2737 | ||
|
|
e86ad435e5 | ||
|
|
f2b42ef00e |
@@ -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
|
||||
- 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.
|
||||
|
||||
@@ -153,6 +153,8 @@ Here’s 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. |
|
||||
| **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. |
|
||||
| **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`
|
||||
<img title="Abogen Voice Mixer" src='https://raw.githubusercontent.com/denizsafak/abogen/refs/heads/main/demo/voice_mixer.png'>
|
||||
|
||||
+2
-2
@@ -230,7 +230,7 @@ if errorlevel 1 (
|
||||
|
||||
:: Install 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 (
|
||||
echo Failed to install setup requirements.
|
||||
pause
|
||||
@@ -250,7 +250,7 @@ if errorlevel 1 (
|
||||
echo Checking and installing project dependencies...
|
||||
if exist %PYPROJECT_FILE% (
|
||||
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 (
|
||||
echo Failed to install from pyproject.toml.
|
||||
pause
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.1.1
|
||||
1.1.2
|
||||
+17
-12
@@ -22,7 +22,7 @@ from PyQt5.QtWidgets import (
|
||||
QLabel,
|
||||
)
|
||||
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 logging # Add logging
|
||||
import urllib.parse
|
||||
@@ -240,20 +240,17 @@ class HandlerDialog(QDialog):
|
||||
tag.decompose()
|
||||
text = clean_text(soup.get_text()).strip()
|
||||
if text:
|
||||
# Use doc_href as the identifier
|
||||
self.content_texts[doc_href] = 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(
|
||||
(epub.Link(doc_href, title, doc_href), [])
|
||||
) # Wrap in tuple and empty list for compatibility
|
||||
@@ -1911,5 +1908,13 @@ class HandlerDialog(QDialog):
|
||||
|
||||
def closeEvent(self, event):
|
||||
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()
|
||||
else:
|
||||
# Fallback: try/except close
|
||||
self.pdf_doc.close()
|
||||
except Exception:
|
||||
pass
|
||||
event.accept()
|
||||
|
||||
@@ -10,6 +10,13 @@ VERSION = get_version()
|
||||
|
||||
# Settings
|
||||
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_DESCRIPTIONS = {
|
||||
@@ -109,6 +116,7 @@ SAMPLE_VOICE_TEXTS = {
|
||||
COLORS = {
|
||||
"BLUE": "#007dff",
|
||||
"RED": "#c0392b",
|
||||
"ORANGE": "#FFA500",
|
||||
"GREEN": "#42ad4a",
|
||||
"GREEN_BG": "rgba(66, 173, 73, 0.1)",
|
||||
"GREEN_BG_HOVER": "rgba(66, 173, 73, 0.15)",
|
||||
|
||||
+446
-466
File diff suppressed because it is too large
Load Diff
+124
-49
@@ -75,6 +75,7 @@ from abogen.constants import (
|
||||
VOICES_INTERNAL,
|
||||
SUPPORTED_LANGUAGES_FOR_SUBTITLE_GENERATION,
|
||||
COLORS,
|
||||
SUBTITLE_FORMATS,
|
||||
)
|
||||
import threading
|
||||
from abogen.voice_formula_gui import VoiceFormulaDialog
|
||||
@@ -124,6 +125,18 @@ class IconProvider(QFileIconProvider):
|
||||
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):
|
||||
# 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;"
|
||||
@@ -646,7 +659,7 @@ class abogen(QWidget):
|
||||
None # Add new variable to track the displayed file path
|
||||
)
|
||||
# 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.last_opened_book_path = None # Track the last opened book path
|
||||
self.last_output_path = None
|
||||
@@ -700,9 +713,6 @@ class abogen(QWidget):
|
||||
self.queued_items = []
|
||||
self.current_queue_index = 0
|
||||
|
||||
# Log lines
|
||||
self._log_lines = []
|
||||
|
||||
self.initUI()
|
||||
self.speed_slider.setValue(int(self.config.get("speed", 1.00) * 100))
|
||||
self.update_speed_label()
|
||||
@@ -785,6 +795,7 @@ class abogen(QWidget):
|
||||
container_layout.addWidget(self.queue_row_widget)
|
||||
self.log_text = QTextEdit(self)
|
||||
self.log_text.setReadOnly(True)
|
||||
self.log_text.setUndoRedoEnabled(False)
|
||||
self.log_text.setFrameStyle(QTextEdit.NoFrame)
|
||||
self.log_text.setStyleSheet("QTextEdit { border: none; }")
|
||||
self.log_text.hide()
|
||||
@@ -944,14 +955,7 @@ class abogen(QWidget):
|
||||
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:
|
||||
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)
|
||||
@@ -1458,16 +1462,12 @@ class abogen(QWidget):
|
||||
self.input_box.hide()
|
||||
self.log_text.show()
|
||||
self.log_text.clear()
|
||||
self._log_lines = []
|
||||
QApplication.processEvents()
|
||||
|
||||
def restore_input_box(self):
|
||||
self.log_text.hide()
|
||||
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):
|
||||
# Use signal-based approach for thread-safe logging
|
||||
if QThread.currentThread() != QApplication.instance().thread():
|
||||
@@ -1479,38 +1479,36 @@ class abogen(QWidget):
|
||||
self._update_log_main_thread(message)
|
||||
|
||||
def _update_log_main_thread(self, message):
|
||||
if not hasattr(self, "_log_lines"):
|
||||
self._log_lines = []
|
||||
txt = self.log_text
|
||||
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):
|
||||
text, spec = message
|
||||
color = "green" if spec is True else ("red" if spec is False else spec)
|
||||
html_line = self.color_text(text, color)
|
||||
fmt.setForeground(QColor(LOG_COLOR_MAP.get(spec, COLORS["LIGHT_DISABLED"])))
|
||||
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:
|
||||
sb.setValue(sb.maximum())
|
||||
|
||||
QApplication.processEvents()
|
||||
|
||||
def _get_queue_progress_format(self, value=None):
|
||||
"""Return the progress bar format string for queue mode."""
|
||||
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['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']};'>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']};'>Input:</span> {item.file_name}<br>"
|
||||
f"<span style='color:{COLORS['LIGHT_DISABLED']};'>Output:</span> {output}</span>"
|
||||
@@ -1988,7 +1986,6 @@ class abogen(QWidget):
|
||||
else:
|
||||
# More items in queue: clear log and reload for next item
|
||||
self.log_text.clear()
|
||||
self._log_lines = []
|
||||
QApplication.processEvents()
|
||||
|
||||
# Start new queued item, if we're using a queued conversion
|
||||
@@ -2032,7 +2029,6 @@ class abogen(QWidget):
|
||||
self.progress_bar.hide()
|
||||
self.restore_input_box()
|
||||
self.log_text.clear()
|
||||
self._log_lines = []
|
||||
|
||||
# Use displayed_file_path instead of selected_file for EPUBs or PDFs
|
||||
display_path = (
|
||||
@@ -2444,7 +2440,6 @@ class abogen(QWidget):
|
||||
self.finish_widget.hide()
|
||||
self.restore_input_box()
|
||||
self.log_text.clear()
|
||||
self._log_lines = []
|
||||
display_path = (
|
||||
self.displayed_file_path
|
||||
if self.displayed_file_path
|
||||
@@ -2484,6 +2479,16 @@ class abogen(QWidget):
|
||||
self.config["use_gpu"] = self.use_gpu
|
||||
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):
|
||||
if self.is_converting:
|
||||
box = QMessageBox(self)
|
||||
@@ -2495,16 +2500,12 @@ class abogen(QWidget):
|
||||
box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
|
||||
box.setDefaultButton(QMessageBox.No)
|
||||
if box.exec_() == QMessageBox.Yes:
|
||||
if (
|
||||
hasattr(self, "conversion_thread")
|
||||
and self.conversion_thread.isRunning()
|
||||
):
|
||||
self.conversion_thread.cancel()
|
||||
self.conversion_thread.wait()
|
||||
self.cleanup_conversion_thread()
|
||||
event.accept()
|
||||
else:
|
||||
event.ignore()
|
||||
else:
|
||||
self.cleanup_conversion_thread()
|
||||
event.accept()
|
||||
|
||||
def show_chapter_options_dialog(self, chapter_count):
|
||||
@@ -2779,6 +2780,17 @@ class abogen(QWidget):
|
||||
# Add seperator"
|
||||
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
|
||||
check_updates_action = QAction("Check for updates at startup", self)
|
||||
check_updates_action.setCheckable(True)
|
||||
@@ -2786,6 +2798,11 @@ class abogen(QWidget):
|
||||
check_updates_action.triggered.connect(self.toggle_check_updates)
|
||||
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
|
||||
about_action = QAction("About", self)
|
||||
about_action.triggered.connect(self.show_about_dialog)
|
||||
@@ -2798,6 +2815,64 @@ class abogen(QWidget):
|
||||
self.config["replace_single_newlines"] = enabled
|
||||
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):
|
||||
"""Open the configuration file location in file explorer."""
|
||||
from abogen.utils import get_user_config_path
|
||||
|
||||
+13
-1
@@ -1,3 +1,4 @@
|
||||
from json import load
|
||||
import os
|
||||
import sys
|
||||
import platform
|
||||
@@ -7,8 +8,19 @@ from PyQt5.QtCore import qInstallMessageHandler, QtMsgType
|
||||
|
||||
# Add the directory to Python path
|
||||
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.utils import get_resource_path
|
||||
from abogen.constants import PROGRAM_NAME, VERSION
|
||||
|
||||
# Set environment variables for AMD ROCm
|
||||
|
||||
@@ -246,6 +246,7 @@ class QueueManager(QDialog):
|
||||
)
|
||||
list_item.setToolTip(tooltip)
|
||||
list_item.setIcon(icon)
|
||||
list_item.setData(Qt.UserRole, file_name)
|
||||
# Use custom widget for display
|
||||
char_count = getattr(item, "total_char_count", 0)
|
||||
widget = QueueListItemWidget(file_name, char_count)
|
||||
@@ -472,9 +473,9 @@ class QueueManager(QDialog):
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
|
||||
item = selected_items[0]
|
||||
display_name = item.text()
|
||||
file_path = item.data(Qt.UserRole)
|
||||
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):
|
||||
QMessageBox.warning(
|
||||
self, "File Not Found", f"The file does not exist."
|
||||
@@ -493,9 +494,9 @@ class QueueManager(QDialog):
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
|
||||
item = selected_items[0]
|
||||
display_name = item.text()
|
||||
file_path = item.data(Qt.UserRole)
|
||||
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):
|
||||
QMessageBox.warning(
|
||||
self, "File Not Found", f"The file does not exist."
|
||||
|
||||
@@ -7,8 +7,6 @@ import subprocess
|
||||
import re
|
||||
from threading import Thread
|
||||
|
||||
# suppress warnings and disable HF hub symlink warnings
|
||||
os.environ["HF_HUB_DISABLE_SYMLINKS_WARNING"] = "1"
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user