mirror of
https://github.com/denizsafak/abogen.git
synced 2026-07-18 13:40:27 +02:00
@@ -1,4 +1,5 @@
|
||||
# v1.1.2 (pre-release)
|
||||
- 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.
|
||||
|
||||
# v1.1.1
|
||||
|
||||
@@ -109,6 +109,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)",
|
||||
|
||||
+42
-40
@@ -52,6 +52,8 @@ from PyQt5.QtGui import (
|
||||
QPolygon,
|
||||
QColor,
|
||||
QMovie,
|
||||
QFont,
|
||||
QTextCharFormat,
|
||||
)
|
||||
from abogen.utils import (
|
||||
load_config,
|
||||
@@ -123,6 +125,15 @@ class IconProvider(QFileIconProvider):
|
||||
def icon(self, 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"],
|
||||
None: COLORS["LIGHT_DISABLED"],
|
||||
}
|
||||
|
||||
class InputBox(QLabel):
|
||||
# Define CSS styles as class constants
|
||||
@@ -646,7 +657,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 +711,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 +793,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()
|
||||
@@ -1458,16 +1467,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 +1484,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 (
|
||||
@@ -1988,7 +1991,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 +2034,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 +2445,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 +2484,12 @@ 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 +2501,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):
|
||||
|
||||
Reference in New Issue
Block a user