from __future__ import annotations from pathlib import Path from PyQt6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QPlainTextEdit, ) from PyQt6.QtCore import QUrl from PyQt6.QtGui import QDesktopServices from workers.hugo_worker import HugoWorker from workers.npm_worker import NpmWorker class HugoPanel(QWidget): def __init__(self, repo_path: Path, parent=None): super().__init__(parent) self._worker = HugoWorker(repo_path, parent=self) self._worker.log_line.connect(self._on_log) self._worker.started.connect(self._on_hugo_started) self._worker.stopped.connect(self._on_hugo_stopped) self._worker.error.connect(lambda e: self._log.appendPlainText(f"[ERRORE] {e}")) self._npm = NpmWorker(repo_path, parent=self) self._npm.log_line.connect(self._on_log) self._npm.finished.connect(self._on_build_finished) self._build_ui() def _build_ui(self): layout = QVBoxLayout(self) top = QHBoxLayout() self._status_label = QLabel("🔴 Hugo server: fermo") self._status_label.setStyleSheet("color:#ff6b6b;font-weight:bold;") top.addWidget(self._status_label) top.addStretch() self._start_btn = QPushButton("▶ Avvia") self._start_btn.clicked.connect(self._on_start_clicked) self._stop_btn = QPushButton("⏹ Ferma") self._stop_btn.clicked.connect(self._worker.stop) self._stop_btn.setEnabled(False) self._build_btn = QPushButton("🔨 Build CSS") self._build_btn.clicked.connect(self._on_build_clicked) top.addWidget(self._start_btn) top.addWidget(self._stop_btn) top.addWidget(self._build_btn) self._url_btn = QPushButton("🌐 http://localhost:1313") self._url_btn.setFlat(True) self._url_btn.setStyleSheet("color:#60a5fa;text-decoration:underline;") self._url_btn.clicked.connect(lambda: QDesktopServices.openUrl(QUrl("http://localhost:1313"))) self._url_btn.setVisible(False) top.addWidget(self._url_btn) layout.addLayout(top) self._log = QPlainTextEdit() self._log.setReadOnly(True) self._log.setStyleSheet("background:#0a0a12;color:#00ff88;font-family:monospace;font-size:11px;") layout.addWidget(self._log) # --- button handlers --- def _on_start_clicked(self): self._status_label.setText("🟡 Build CSS...") self._status_label.setStyleSheet("color:#fbbf24;font-weight:bold;") self._start_btn.setEnabled(False) self._stop_btn.setEnabled(False) self._build_btn.setEnabled(False) self._log.appendPlainText("─── npm run build ───") self._npm.run() def _on_build_clicked(self): self._build_btn.setEnabled(False) self._log.appendPlainText("─── npm run build ───") self._npm.run() # --- npm worker callbacks --- def _on_build_finished(self, success: bool): if success: self._log.appendPlainText("─── build OK ───") if not self._worker.is_running: # launched via Avvia → now start hugo self._log.appendPlainText("─── hugo server avvia ───") self._worker.start() else: # manual rebuild while server running self._build_btn.setEnabled(True) else: self._log.appendPlainText("─── build FALLITO ───") if not self._worker.is_running: # failed before hugo started → restore idle state self._status_label.setText("🔴 Hugo server: fermo") self._status_label.setStyleSheet("color:#ff6b6b;font-weight:bold;") self._start_btn.setEnabled(True) self._build_btn.setEnabled(True) else: self._build_btn.setEnabled(True) # --- hugo worker callbacks --- def _on_hugo_started(self): self._status_label.setText("🟢 Hugo server: in esecuzione") self._status_label.setStyleSheet("color:#00ff88;font-weight:bold;") self._start_btn.setEnabled(False) self._stop_btn.setEnabled(True) self._build_btn.setEnabled(True) self._url_btn.setVisible(True) def _on_hugo_stopped(self): self._status_label.setText("🔴 Hugo server: fermo") self._status_label.setStyleSheet("color:#ff6b6b;font-weight:bold;") self._start_btn.setEnabled(True) self._stop_btn.setEnabled(False) self._build_btn.setEnabled(True) self._url_btn.setVisible(False) # --- log --- def _on_log(self, line: str): self._log.appendPlainText(line) # --- lifecycle --- def stop_server(self): self._worker.stop() def closeEvent(self, event): self.stop_server() super().closeEvent(event)