From 993950b7733ba9300915955ec6e51e1f21dad806 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Mon, 19 Oct 2026 21:28:54 +0200 Subject: 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 --- sb_builder/dashboard.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'sb_builder/dashboard.py') 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("   ".join( - f'■ {html.escape(k)} {num(v)}' + f'■ ' + f'' + f'{html.escape(k)} {num(v)}' for k, v in order)) def show_jobs(self, jobs): -- cgit v1.2.3