--- /dev/null
+from __future__ import annotations
+from pathlib import Path
+from PyQt6.QtWidgets import (
+ QWidget, QVBoxLayout, QHBoxLayout, QTabWidget,
+ QTableWidget, QTableWidgetItem, QPushButton,
+ QLabel, QDialog, QFormLayout, QLineEdit, QMessageBox,
+)
+from PyQt6.QtCore import Qt
+from PyQt6.QtGui import QColor
+from core.taxonomy import TaxonomyModel, load_taxonomy, save_taxonomy
+
+class AddTermDialog(QDialog):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.setWindowTitle("Aggiungi termine")
+ layout = QVBoxLayout(self)
+ form = QFormLayout()
+ self._it = QLineEdit()
+ self._en = QLineEdit()
+ form.addRow("IT:", self._it)
+ form.addRow("EN:", self._en)
+ layout.addLayout(form)
+ btns = QHBoxLayout()
+ ok = QPushButton("Aggiungi")
+ ok.clicked.connect(self.accept)
+ cancel = QPushButton("Annulla")
+ cancel.clicked.connect(self.reject)
+ btns.addStretch()
+ btns.addWidget(cancel)
+ btns.addWidget(ok)
+ layout.addLayout(btns)
+
+ @property
+ def it_term(self) -> str:
+ return self._it.text().strip()
+
+ @property
+ def en_term(self) -> str:
+ return self._en.text().strip()
+
+class TaxonomyView(QWidget):
+ def __init__(self, blog_root: Path, parent=None):
+ super().__init__(parent)
+ self._blog_root = blog_root
+ self._tags_it = blog_root / "docs" / "tags-it.txt"
+ self._tags_en = blog_root / "docs" / "tags-en.txt"
+ self._model: TaxonomyModel | None = None
+ self._build_ui()
+ self.load()
+
+ def _build_ui(self):
+ layout = QVBoxLayout(self)
+
+ tabs = QTabWidget()
+
+ tags_tab = QWidget()
+ tl = QVBoxLayout(tags_tab)
+ self._tags_table = QTableWidget(0, 2)
+ self._tags_table.setHorizontalHeaderLabels(["๐ฎ๐น Italiano", "๐ฌ๐ง English"])
+ self._tags_table.horizontalHeader().setStretchLastSection(True)
+ tl.addWidget(self._tags_table)
+ tag_btns = QHBoxLayout()
+ add_tag_btn = QPushButton("โ Aggiungi termine")
+ add_tag_btn.clicked.connect(self._add_term)
+ save_tags_btn = QPushButton("๐พ Salva")
+ save_tags_btn.clicked.connect(self._save)
+ tag_btns.addWidget(add_tag_btn)
+ tag_btns.addStretch()
+ tag_btns.addWidget(save_tags_btn)
+ tl.addLayout(tag_btns)
+ tabs.addTab(tags_tab, "๐ท Tags")
+
+ layout.addWidget(tabs)
+
+ self._status = QLabel("")
+ self._status.setStyleSheet("color:#888;font-size:10px;padding:4px;")
+ layout.addWidget(self._status)
+
+ def load(self):
+ if not self._tags_it.exists():
+ self._status.setText("tags-it.txt non trovato.")
+ return
+ self._model = load_taxonomy(self._tags_it, self._tags_en)
+ self._populate_table()
+
+ def _populate_table(self):
+ if not self._model:
+ return
+ self._tags_table.setRowCount(0)
+ for it_term, en_term in sorted(self._model.it_to_en.items()):
+ row = self._tags_table.rowCount()
+ self._tags_table.insertRow(row)
+ self._tags_table.setItem(row, 0, QTableWidgetItem(it_term))
+ self._tags_table.setItem(row, 1, QTableWidgetItem(en_term))
+
+ for orphan in self._model.orphans_it:
+ row = self._tags_table.rowCount()
+ self._tags_table.insertRow(row)
+ it_item = QTableWidgetItem(orphan)
+ it_item.setForeground(QColor("#ff6b6b"))
+ en_item = QTableWidgetItem("โ mancante")
+ en_item.setForeground(QColor("#ff6b6b"))
+ self._tags_table.setItem(row, 0, it_item)
+ self._tags_table.setItem(row, 1, en_item)
+
+ self._status.setText(
+ f"{len(self._model.it_to_en)} coppie ยท {len(self._model.orphans_it)} IT orfani ยท {len(self._model.orphans_en)} EN orfani"
+ )
+
+ def _add_term(self):
+ dlg = AddTermDialog(self)
+ if dlg.exec() and dlg.it_term and dlg.en_term:
+ if self._model:
+ self._model.it_to_en[dlg.it_term] = dlg.en_term
+ self._populate_table()
+
+ def _save(self):
+ if not self._model:
+ return
+ updated: dict[str, str] = {}
+ for row in range(self._tags_table.rowCount()):
+ it_item = self._tags_table.item(row, 0)
+ en_item = self._tags_table.item(row, 1)
+ if it_item and en_item:
+ it_val = it_item.text().strip()
+ en_val = en_item.text().strip()
+ if it_val and en_val and en_val != "โ mancante":
+ updated[it_val] = en_val
+ self._model.it_to_en = updated
+ save_taxonomy(self._model, self._tags_it, self._tags_en)
+ self._status.setText("Salvato.")