]> danix's work - publisher.git/commitdiff
fix: replace text elide workarounds with QStyledItemDelegate for proper two-line... v1.1
authorDanilo M. <redacted>
Sun, 3 May 2026 11:10:05 +0000 (13:10 +0200)
committerDanilo M. <redacted>
Sun, 3 May 2026 11:10:05 +0000 (13:10 +0200)
ui/articles_view.py

index 4ac87d58c70860120167010a18d564acb7f80bbe..d905fde2705f2b22ee83ff8b11eccd2e1fa54e31 100644 (file)
@@ -2,11 +2,51 @@ from __future__ import annotations
 from PyQt6.QtWidgets import (
     QWidget, QVBoxLayout, QTabWidget,
     QListWidget, QListWidgetItem, QLabel,
+    QStyledItemDelegate, QApplication,
 )
-from PyQt6.QtCore import Qt, pyqtSignal, QSize
-from PyQt6.QtGui import QColor
+from PyQt6.QtCore import Qt, pyqtSignal, QSize, QRect
+from PyQt6.QtGui import QColor, QPainter, QFontMetrics
 from core.models import Article
 
+_LINE2_ROLE = Qt.ItemDataRole.UserRole + 1
+
+
+class ArticleItemDelegate(QStyledItemDelegate):
+    def paint(self, painter: QPainter, option, index):
+        painter.save()
+        self.initStyleOption(option, index)
+        style = option.widget.style() if option.widget else QApplication.style()
+        style.drawPrimitive(style.PrimitiveElement.PE_PanelItemViewItem, option, painter, option.widget)
+
+        rect: QRect = option.rect
+        fm = QFontMetrics(option.font)
+        line_h = fm.height()
+        pad = 4
+
+        line1 = index.data(Qt.ItemDataRole.DisplayRole) or ""
+        line2 = index.data(_LINE2_ROLE) or ""
+        fg = index.data(Qt.ItemDataRole.ForegroundRole)
+
+        painter.setPen(fg.color() if fg else option.palette.text().color())
+        r1 = QRect(rect.left() + pad, rect.top() + pad, rect.width() - pad * 2, line_h)
+        painter.drawText(r1, Qt.TextFlag.TextSingleLine, line1)
+
+        if line2:
+            painter.setPen(QColor("#888"))
+            r2 = QRect(rect.left() + pad, rect.top() + pad + line_h + 2, rect.width() - pad * 2, line_h)
+            painter.drawText(r2, Qt.TextFlag.TextSingleLine, line2)
+
+        painter.restore()
+
+    def sizeHint(self, option, index):
+        fm = QFontMetrics(option.font)
+        line_h = fm.height()
+        pad = 4
+        line2 = index.data(_LINE2_ROLE) or ""
+        height = (line_h * 2 + 2 + pad * 2) if line2 else (line_h + pad * 2)
+        return QSize(0, height)
+
+
 class ArticleItem(QListWidgetItem):
     def __init__(self, article: Article):
         super().__init__()
@@ -30,15 +70,15 @@ class ArticleItem(QListWidgetItem):
             parts.append(f"[{article.meta_categories}]")
         line2 = "  ".join(parts) if parts else ""
 
-        text = f"{line1}\n{line2}" if line2 else line1
-        self.setText(text)
-        self.setSizeHint(QSize(0, 42) if line2 else QSize(0, 26))
+        self.setText(line1)
+        self.setData(_LINE2_ROLE, line2)
 
         if article.draft:
             self.setForeground(QColor("#f59e0b"))
         elif not article.has_translation:
             self.setForeground(QColor("#ff6b6b"))
 
+
 class ArticlesView(QWidget):
     article_selected = pyqtSignal(object)  # Article
     translate_requested = pyqtSignal(object)  # Article
@@ -54,11 +94,9 @@ class ArticlesView(QWidget):
         self._tabs = QTabWidget()
         self._tabs.setStyleSheet("QTabBar::tab { padding: 6px 16px; }")
         self._list_it = QListWidget()
-        self._list_it.setWordWrap(True)
-        self._list_it.setTextElideMode(Qt.TextElideMode.ElideNone)
+        self._list_it.setItemDelegate(ArticleItemDelegate(self._list_it))
         self._list_en = QListWidget()
-        self._list_en.setWordWrap(True)
-        self._list_en.setTextElideMode(Qt.TextElideMode.ElideNone)
+        self._list_en.setItemDelegate(ArticleItemDelegate(self._list_en))
         self._tabs.addTab(self._list_it, "🇮🇹 Italiano")
         self._tabs.addTab(self._list_en, "🇬🇧 English")
         layout.addWidget(self._tabs)
@@ -76,6 +114,7 @@ class ArticlesView(QWidget):
             else:
                 self._list_en.addItem(item)
 
+
 class MissingTranslationView(QWidget):
     article_selected = pyqtSignal(object)  # Article
     translate_requested = pyqtSignal(object)  # Article
@@ -90,8 +129,7 @@ class MissingTranslationView(QWidget):
         header.setStyleSheet("color: #ff6b6b; font-weight: bold; font-size: 13px; padding: 10px;")
         layout.addWidget(header)
         self._list = QListWidget()
-        self._list.setWordWrap(True)
-        self._list.setTextElideMode(Qt.TextElideMode.ElideNone)
+        self._list.setItemDelegate(ArticleItemDelegate(self._list))
         layout.addWidget(self._list)
         self._list.itemClicked.connect(lambda item: self.article_selected.emit(item.article))
 
@@ -102,5 +140,5 @@ class MissingTranslationView(QWidget):
             lang_other = "🇬🇧" if a.lang == "it" else "🇮🇹"
             item = ArticleItem(a)
             item.setText(f"{a.slug}  [manca {lang_other}]  ({a.lang.upper()})")
-            item.setSizeHint(QSize(0, 26))
+            item.setData(_LINE2_ROLE, "")
             self._list.addItem(item)