From: Danilo M. Date: Sun, 3 May 2026 11:10:05 +0000 (+0200) Subject: fix: replace text elide workarounds with QStyledItemDelegate for proper two-line... X-Git-Tag: v1.1 X-Git-Url: https://git.danix.xyz/?a=commitdiff_plain;h=fa471fc0de8708a1d3fa99cac6e309adb53303fc;p=publisher.git fix: replace text elide workarounds with QStyledItemDelegate for proper two-line rendering --- diff --git a/ui/articles_view.py b/ui/articles_view.py index 4ac87d5..d905fde 100644 --- a/ui/articles_view.py +++ b/ui/articles_view.py @@ -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)