gui/mozregui/report_delegate.py (94 lines of code) (raw):
from PySide6.QtCore import QEvent, QRect, Qt, Signal
from PySide6.QtGui import QIcon, QPainter, QPen, QPixmap
from PySide6.QtWidgets import (
QApplication,
QStyle,
QStyledItemDelegate,
QStyleOptionProgressBar,
QWidget,
)
from mozregui.report import VERDICT_TO_ROW_COLORS
from mozregui.ui.ask_verdict import Ui_AskVerdict
from mozregui.utils import is_dark_mode_enabled
VERDICTS = ("good", "bad", "skip", "retry", "other...")
class AskVerdict(QWidget):
icons_cache = {}
def __init__(self, parent, delegate):
QWidget.__init__(self, parent)
self.delegate = delegate
self.emitted = False
self.ui = Ui_AskVerdict()
self.ui.setupUi(self)
# build verdict icons
if not AskVerdict.icons_cache:
self._build_icon_cache()
# set combo verdict
for text in ("other...", "skip", "retry"):
self.ui.comboVerdict.addItem(AskVerdict.icons_cache[text], text)
model = self.ui.comboVerdict.model()
model.itemFromIndex(model.index(0, 0)).setSelectable(False)
self.ui.comboVerdict.activated.connect(self.on_dropdown_item_activated)
self.ui.goodVerdict.clicked.connect(self.on_good_bad_button_clicked)
self.ui.goodVerdict.setIcon(AskVerdict.icons_cache["good"])
self.ui.badVerdict.clicked.connect(self.on_good_bad_button_clicked)
self.ui.badVerdict.setIcon(AskVerdict.icons_cache["bad"])
def _build_icon_cache(self):
for text in VERDICTS:
if is_dark_mode_enabled():
color = VERDICT_TO_ROW_COLORS.get(text[0] + "_dark")
else:
color = VERDICT_TO_ROW_COLORS.get(text[0])
pixmap = QPixmap(16, 16)
pixmap.fill(Qt.transparent)
if color:
painter = QPainter(pixmap)
painter.setPen(QPen(self.palette().windowText().color()))
painter.setBrush(color)
painter.drawEllipse(0, 0, 15, 15)
painter.end()
AskVerdict.icons_cache[text] = QIcon(pixmap)
def _update_icons(self):
self.ui.goodVerdict.setIcon(AskVerdict.icons_cache["good"])
self.ui.badVerdict.setIcon(AskVerdict.icons_cache["bad"])
for i in range(self.ui.comboVerdict.count()):
text = str(self.ui.comboVerdict.itemText(i))
self.ui.comboVerdict.setItemIcon(i, AskVerdict.icons_cache[text])
def on_dropdown_item_activated(self):
self.delegate.got_verdict.emit(str(self.ui.comboVerdict.currentText())[0].lower())
self.emitted = True
def on_good_bad_button_clicked(self):
self.delegate.got_verdict.emit(str(self.sender().text())[0].lower())
self.emitted = True
def event(self, event: QEvent) -> bool:
if event.type() == QEvent.PaletteChange:
self._build_icon_cache()
self._update_icons()
return True
return super().event(event)
class ReportItemDelegate(QStyledItemDelegate):
got_verdict = Signal(str)
def __init__(self, parent=None, *args):
QStyledItemDelegate.__init__(self, parent, *args)
def createEditor(self, parent, option, index):
if index.model().get_item(index).waiting_evaluation:
return AskVerdict(parent, self)
else:
return QStyledItemDelegate.createEditor(self, parent, option, index)
def paint(self, painter, option, index):
# if item selected, override default theme
# Keeps verdict color for cells and use a bold font
if option.state & QStyle.State_Selected:
option.state &= ~QStyle.State_Selected
option.font.setBold(True)
QStyledItemDelegate.paint(self, painter, option, index)
item = index.model().get_item(index)
if item and item.downloading:
# Draw progress bar
progressBarOption = QStyleOptionProgressBar()
progressBarHeight = option.rect.height() / 4
progressBarOption.rect = QRect(
option.rect.x(),
option.rect.y() + (option.rect.height() - progressBarHeight),
option.rect.width(),
progressBarHeight,
)
progressBarOption.minimum = 0
progressBarOption.maximum = 100
progressBarOption.textAlignment = Qt.AlignCenter
progressBarOption.progress = item.progress
QApplication.style().drawControl(QStyle.CE_ProgressBar, progressBarOption, painter)