Added loading gif animation to book handler window

This commit is contained in:
Deniz Şafak
2025-10-22 01:21:55 +03:00
parent f5d1def330
commit f80c86b00d
2 changed files with 77 additions and 21 deletions
+3
View File
@@ -1,3 +1,6 @@
# 1.2.1 (pre-release)
- Added loading gif animation to book handler window.
# 1.2.0 # 1.2.0
- Added `Line` option to subtitle generation modes, allowing subtitles to be generated based on line breaks in the text, by @mleg in #94. - Added `Line` option to subtitle generation modes, allowing subtitles to be generated based on line breaks in the text, by @mleg in #94.
- Added a loading indicator to the book handler window for better user experience during book preprocessing. - Added a loading indicator to the book handler window for better user experience during book preprocessing.
+74 -21
View File
@@ -20,8 +20,9 @@ from PyQt5.QtWidgets import (
QMenu, QMenu,
QLabel, QLabel,
) )
from PyQt5.QtCore import Qt, QThread, pyqtSignal from PyQt5.QtCore import Qt, QThread, pyqtSignal, QSize
from abogen.utils import clean_text, calculate_text_length, detect_encoding from PyQt5.QtGui import QMovie
from abogen.utils import clean_text, calculate_text_length, detect_encoding, get_resource_path
import os import os
import logging # Add logging import logging # Add logging
import urllib.parse import urllib.parse
@@ -206,40 +207,92 @@ class HandlerDialog(QDialog):
def _create_loading_overlay(self): def _create_loading_overlay(self):
"""Create a simple centered QLabel used as loading indicator. """Create a centered loading indicator with a GIF on the left and text on the right.
This label is added to the dialog's main layout above the splitter so The indicator is added to the dialog's main layout above the splitter so
when the splitter is hidden only the text is visible. when the splitter is hidden only the indicator is visible.
""" """
try: try:
label = QLabel(self) # Container to hold gif + text and allow centering via stretches
label.setAlignment(Qt.AlignCenter) container = QWidget(self)
# larger plain text per request container.setVisible(False)
label.setStyleSheet("font-size: 14pt;") h = QHBoxLayout(container)
label.setVisible(False) h.setContentsMargins(0, 8, 0, 8)
# insert at top of main layout if present, otherwise keep as child h.setSpacing(10)
# Left: GIF label (animated)
gif_label = QLabel(container)
gif_label.setVisible(False)
loading_gif_path = get_resource_path("abogen.assets", "loading.gif")
movie = None
if loading_gif_path:
try:
movie = QMovie(loading_gif_path)
# Make GIF smaller so it doesn't dominate the text
movie.setScaledSize(QSize(25, 25))
gif_label.setMovie(movie)
gif_label.setFixedSize(25, 25)
gif_label.setVisible(True)
except Exception:
movie = None
# Right: Text label
text_label = QLabel(container)
text_label.setStyleSheet("font-size: 14pt;")
# Add stretches to center the content horizontally
h.addStretch(1)
h.addWidget(gif_label, 0, Qt.AlignVCenter)
h.addWidget(text_label, 0, Qt.AlignVCenter)
h.addStretch(1)
# Insert at top of main layout if present, otherwise keep as child
try: try:
layout = self.layout() layout = self.layout()
if layout is not None: if layout is not None:
layout.insertWidget(0, label) layout.insertWidget(0, container)
except Exception: except Exception:
pass pass
self._loading_label = label
# Store refs
self._loading_container = container
self._loading_gif_label = gif_label
self._loading_text_label = text_label
self._loading_movie = movie
except Exception: except Exception:
self._loading_label = None self._loading_container = None
self._loading_gif_label = None
self._loading_text_label = None
self._loading_movie = None
def _show_loading_overlay(self, text: str): def _show_loading_overlay(self, text: str):
lbl = getattr(self, '_loading_label', None) container = getattr(self, '_loading_container', None)
if lbl is None: text_lbl = getattr(self, '_loading_text_label', None)
movie = getattr(self, '_loading_movie', None)
gif_lbl = getattr(self, '_loading_gif_label', None)
if container is None or text_lbl is None:
return return
lbl.setText(text) text_lbl.setText(text)
lbl.setVisible(True) if movie is not None and gif_lbl is not None:
try:
movie.start()
gif_lbl.setVisible(True)
except Exception:
pass
container.setVisible(True)
def _hide_loading_overlay(self): def _hide_loading_overlay(self):
lbl = getattr(self, '_loading_label', None) container = getattr(self, '_loading_container', None)
if lbl is None: movie = getattr(self, '_loading_movie', None)
if container is None:
return return
lbl.setVisible(False) if movie is not None:
try:
movie.stop()
except Exception:
pass
container.setVisible(False)
def _start_background_load(self): def _start_background_load(self):