diff options
Diffstat (limited to 'ui/main_window.py')
| -rw-r--r-- | ui/main_window.py | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/ui/main_window.py b/ui/main_window.py new file mode 100644 index 0000000..9f0594b --- /dev/null +++ b/ui/main_window.py @@ -0,0 +1,144 @@ +from __future__ import annotations +from PyQt6.QtWidgets import ( + QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, + QLabel, QPushButton, QStackedWidget, QFrame, QSizePolicy, +) +from PyQt6.QtCore import Qt, QFileSystemWatcher +from PyQt6.QtGui import QFont +from pathlib import Path +from core.config import Config +from core.article_scanner import scan_articles +from core.models import Article + +class SidebarButton(QPushButton): + def __init__(self, text: str, parent=None): + super().__init__(text, parent) + self.setFlat(True) + self.setCheckable(True) + self.setStyleSheet(""" + QPushButton { text-align: left; padding: 5px 10px; border-radius: 4px; color: #888; } + QPushButton:checked { background: #2a2a4e; color: #a855f7; } + QPushButton:hover:!checked { background: #1a1a2e; color: #ccc; } + """) + +class MainWindow(QMainWindow): + def __init__(self, config: Config, parent=None): + super().__init__(parent) + self.config = config + self._articles: list[Article] = [] + self._watcher = QFileSystemWatcher(self) + self._watcher.directoryChanged.connect(self._on_fs_change) + self.setWindowTitle("my-publisher") + self.setMinimumSize(1100, 700) + self._build_ui() + self._refresh_articles() + self._setup_watcher() + + def _build_ui(self): + central = QWidget() + self.setCentralWidget(central) + root = QHBoxLayout(central) + root.setContentsMargins(0, 0, 0, 0) + root.setSpacing(0) + + # Sidebar + sidebar = self._build_sidebar() + root.addWidget(sidebar) + + # Divider + line = QFrame() + line.setFrameShape(QFrame.Shape.VLine) + line.setStyleSheet("color: #2a2a4e;") + root.addWidget(line) + + # Content stack + self._stack = QStackedWidget() + root.addWidget(self._stack, stretch=1) + + # Placeholder pages (replaced in later tasks) + for name in ["articles", "no_translation", "new_article", "taxonomy", + "media", "translations", "git", "hugo"]: + w = QLabel(f"[{name}]") + w.setAlignment(Qt.AlignmentFlag.AlignCenter) + self._stack.addWidget(w) + setattr(self, f"_page_{name}", self._stack.count() - 1) + + def _build_sidebar(self) -> QWidget: + w = QWidget() + w.setFixedWidth(210) + w.setStyleSheet("background: #1a1a2e;") + layout = QVBoxLayout(w) + layout.setContentsMargins(8, 12, 8, 12) + layout.setSpacing(2) + + header = QHBoxLayout() + title = QLabel("๐ฐ my-publisher") + title.setStyleSheet("color: #fff; font-weight: bold; font-size: 13px; padding: 4px 8px;") + header.addWidget(title) + self._refresh_btn = QPushButton("๐") + self._refresh_btn.setFlat(True) + self._refresh_btn.setFixedSize(28, 28) + self._refresh_btn.setStyleSheet("color: #555; border: none;") + self._refresh_btn.clicked.connect(self._refresh_articles) + header.addWidget(self._refresh_btn) + layout.addLayout(header) + + def section(text): + lbl = QLabel(text) + lbl.setStyleSheet("color: #a855f7; font-size: 9px; text-transform: uppercase; letter-spacing: 1px; padding: 8px 8px 2px;") + layout.addWidget(lbl) + + self._btn_group: list[SidebarButton] = [] + + def btn(icon_text: str, page_attr: str) -> SidebarButton: + b = SidebarButton(icon_text) + b.clicked.connect(lambda: self._show_page(page_attr, b)) + layout.addWidget(b) + self._btn_group.append(b) + return b + + section("CONTENUTO") + btn("๐ Articoli", "_page_articles") + self._btn_no_trans = btn("โ ๏ธ Senza Traduzione", "_page_no_translation") + self._badge_no_trans = QLabel("0") + self._badge_no_trans.setStyleSheet("background:#3a1a1a;color:#ff6b6b;border-radius:8px;padding:1px 6px;font-size:10px;") + btn("โ Nuovo articolo", "_page_new_article") + btn("๐ท Tassonomia", "_page_taxonomy") + btn("๐ผ Media", "_page_media") + + section("WORKFLOW") + btn("๐ Traduzioni", "_page_translations") + btn("๐ง Git ops", "_page_git") + btn("๐ Hugo server", "_page_hugo") + + section("DEPLOY") + btn("๐งช Test (master)", "_page_git") + btn("๐ข Production", "_page_git") + + layout.addStretch() + return w + + def _show_page(self, page_attr: str, active_btn: SidebarButton): + for b in self._btn_group: + b.setChecked(False) + active_btn.setChecked(True) + self._stack.setCurrentIndex(getattr(self, page_attr)) + + def _refresh_articles(self): + if not self.config.blog_repo: + return + self._articles = scan_articles(Path(self.config.blog_repo)) + missing = [a for a in self._articles if not a.has_translation] + self._badge_no_trans.setText(str(len(missing))) + + def _setup_watcher(self): + if not self.config.blog_repo: + return + root = Path(self.config.blog_repo) + for lang in ("it", "en"): + d = root / "content" / lang / "articles" + if d.exists(): + self._watcher.addPath(str(d)) + + def _on_fs_change(self, _path: str): + self._refresh_articles() |
