82 lines
2.8 KiB
Python
82 lines
2.8 KiB
Python
"""Fenêtre de suivi du scraping automatique (IA) : journal horodaté des
|
|
étapes (extraction, recherche du lien suivant, navigation...) et
|
|
progression, en complément des messages transitoires de la barre de
|
|
statut — voir MainWindow._toggle_auto_scrape / _auto_scrape_*.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from typing import Callable
|
|
|
|
from PySide6.QtCore import Qt
|
|
from PySide6.QtWidgets import (
|
|
QDialog,
|
|
QHBoxLayout,
|
|
QLabel,
|
|
QProgressBar,
|
|
QPushButton,
|
|
QTextEdit,
|
|
QVBoxLayout,
|
|
QWidget,
|
|
)
|
|
|
|
|
|
class AutoScrapeDialog(QDialog):
|
|
"""Non modale : reste affichée sans bloquer la navigation ni le reste
|
|
de l'appli pendant que le scraping automatique tourne. Une seule
|
|
instance est réutilisée d'un lancement à l'autre (voir
|
|
MainWindow._toggle_auto_scrape) — fermer la fenêtre (X) la masque
|
|
seulement, elle n'arrête pas le scraping en cours."""
|
|
|
|
def __init__(self, parent: QWidget | None, on_stop: Callable[[], None]) -> None:
|
|
super().__init__(parent)
|
|
self.setWindowTitle("Scraping automatique (IA)")
|
|
self.resize(560, 420)
|
|
self.setWindowModality(Qt.WindowModality.NonModal)
|
|
self._on_stop = on_stop
|
|
|
|
layout = QVBoxLayout(self)
|
|
|
|
self.status_label = QLabel("En attente…")
|
|
layout.addWidget(self.status_label)
|
|
|
|
self.progress_bar = QProgressBar()
|
|
self.progress_bar.setRange(0, 1)
|
|
self.progress_bar.setValue(0)
|
|
layout.addWidget(self.progress_bar)
|
|
|
|
self.log_view = QTextEdit()
|
|
self.log_view.setReadOnly(True)
|
|
layout.addWidget(self.log_view, stretch=1)
|
|
|
|
buttons = QHBoxLayout()
|
|
buttons.addStretch(1)
|
|
self.stop_button = QPushButton("⏹ Arrêter le scraping")
|
|
self.stop_button.clicked.connect(self._on_stop)
|
|
buttons.addWidget(self.stop_button)
|
|
layout.addLayout(buttons)
|
|
|
|
def reset(self, max_chapters: int) -> None:
|
|
self.log_view.clear()
|
|
self.set_progress(0, max_chapters)
|
|
|
|
def set_progress(self, count: int, max_chapters: int) -> None:
|
|
if max_chapters > 0:
|
|
self.progress_bar.setRange(0, max_chapters)
|
|
self.progress_bar.setValue(count)
|
|
self.status_label.setText(f"Chapitre {count}/{max_chapters}")
|
|
else:
|
|
# 0 = pas de limite fixe : Qt anime automatiquement une barre
|
|
# "indéterminée" quand min == max == 0.
|
|
self.progress_bar.setRange(0, 0)
|
|
self.status_label.setText(f"Chapitre {count} (illimité)")
|
|
|
|
def log(self, message: str) -> None:
|
|
timestamp = datetime.now().strftime("%H:%M:%S")
|
|
self.log_view.append(f"[{timestamp}] {message}")
|
|
|
|
def closeEvent(self, event) -> None: # noqa: N802 (nom imposé par Qt)
|
|
event.ignore()
|
|
self.hide()
|