aboutsummaryrefslogtreecommitdiffstats
path: root/sb_builder/dashboard.py
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-19 21:28:54 +0200
committerDanilo M. <danix@danix.xyz>2026-10-19 21:28:54 +0200
commit993950b7733ba9300915955ec6e51e1f21dad806 (patch)
treed8800305748d96581f3bea06eeb9b1a1da979a49 /sb_builder/dashboard.py
parent5609a744ef5e89c4d57a5239199a6afe5497590e (diff)
downloadsb-builder-993950b7733ba9300915955ec6e51e1f21dad806.tar.gz
sb-builder-993950b7733ba9300915955ec6e51e1f21dad806.zip
Results tab with build logs; count only real packages
sbb-remote 0.4.0: results lists slackrepo's last attempt per package (newest first, with built version and whether a log dir exists), and build-log returns the end of a package's build.log (512 KB) plus its resource.log, accepting only category/pkg paths. Result counts skip the legacy buildresults rows keyed by package file name: the 213 "bad" on the Dashboard matched no package. GUI: a Results tab (chips per result, table sorted by attempt time, detail pane, log viewer window that keeps the failure at the end), opened from the ribbon or by clicking a result in the Dashboard bar or legend, filtered to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'sb_builder/dashboard.py')
-rw-r--r--sb_builder/dashboard.py22
1 files changed, 20 insertions, 2 deletions
diff --git a/sb_builder/dashboard.py b/sb_builder/dashboard.py
index 8c98040..a8de823 100644
--- a/sb_builder/dashboard.py
+++ b/sb_builder/dashboard.py
@@ -104,7 +104,9 @@ class Tile(Card):
class StackedBar(QWidget):
- """Horizontal part-to-whole bar; hover a segment for its label and count."""
+ """Horizontal part-to-whole bar; hover a segment for its count, click to open it."""
+
+ clicked = pyqtSignal(str)
def __init__(self):
super().__init__()
@@ -135,6 +137,14 @@ class StackedBar(QWidget):
p.setBrush(color)
p.drawRoundedRect(rect, 4, 4)
+ def label_at(self, pos):
+ return next((label for rect, label, _c, _col in self.rects() if rect.contains(pos)), None)
+
+ def mouseReleaseEvent(self, e):
+ label = self.label_at(e.position())
+ if label and e.button() == Qt.MouseButton.LeftButton:
+ self.clicked.emit(label)
+
def event(self, e):
if e.type() == QEvent.Type.ToolTip:
hit = next((f"{label}: {count:,}" for rect, label, count, _ in self.rects()
@@ -239,6 +249,8 @@ class Meter(QWidget):
class Dashboard(QWidget):
+ result_clicked = pyqtSignal(str) # a slackrepo result kind, from the bar or legend
+
def __init__(self, parent=None):
super().__init__(parent)
self.setStyleSheet("QFrame#card { background: palette(base);"
@@ -258,6 +270,9 @@ class Dashboard(QWidget):
self.legend = QLabel(NA)
self.legend.setTextFormat(Qt.TextFormat.RichText)
self.legend.setWordWrap(True)
+ self.legend.linkActivated.connect(self.result_clicked)
+ self.bar.clicked.connect(self.result_clicked)
+ self.bar.setCursor(Qt.CursorShape.PointingHandCursor)
self.results.body.addWidget(self.bar)
self.results.body.addWidget(self.legend)
self.results.body.addStretch()
@@ -341,11 +356,14 @@ class Dashboard(QWidget):
self.legend.setText(NA)
return
gray = self.palette().color(QPalette.ColorRole.PlaceholderText) # Mid can match the background
+ ink = self.palette().color(QPalette.ColorRole.WindowText).name() # links in text color
order = sorted(sr["results"].items(),
key=lambda kv: (list(STATUS).index(kv[0]) if kv[0] in STATUS else 99, kv[0]))
self.bar.set_parts([(k, v, QColor(STATUS.get(k)) if k in STATUS else gray) for k, v in order])
self.legend.setText("&nbsp;&nbsp;&nbsp;".join(
- f'<span style="color:{STATUS.get(k, gray.name())}">&#9632;</span> {html.escape(k)} {num(v)}'
+ f'<span style="color:{STATUS.get(k, gray.name())}">&#9632;</span> '
+ f'<a href="{html.escape(k)}" style="color:{ink}; text-decoration:none">'
+ f'{html.escape(k)} {num(v)}</a>'
for k, v in order))
def show_jobs(self, jobs):