sky tab: add Msg column with 10s activity indicator per satellite row

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 17:33:43 +02:00
co-authored by Claude Sonnet 4.6
parent 7862989fd4
commit d54259a772
+44 -2
View File
@@ -18,9 +18,11 @@ from PyQt5.QtGui import QColor, QBrush
from data_model import ReceiverManager, GNSS_NAMES, GNSS_COLORS
from sky_widget import SkyPlotWidget
_COL_HEADERS = ['GNSS', 'SV', 'Elev °', 'Az °', 'C/N₀', 'Fix', 'Receiver']
_COL_HEADERS = ['GNSS', 'SV', 'Elev °', 'Az °', 'C/N₀', 'Fix', 'Receiver', 'Msg']
_COL_MSG = len(_COL_HEADERS) - 1
_TRAIL_MAXLEN = 86400 # 24 hours at 1 Hz
_TRAIL_MAX_HOURS = 24
_MSG_HIGHLIGHT_MS = 10_000
class SkyTab(QWidget):
@@ -33,6 +35,7 @@ class SkyTab(QWidget):
self._info_cards: dict = {} # rid -> QFrame
self._info_labels: dict = {} # rid -> (lbl_pdop, lbl_visible, lbl_used)
self._trail: dict = {} # (rid, gnss_id, sv_id) -> deque[(elev, azim)]
self._hi_timers: dict = {} # (rid, gnss_id, sv_id) -> QTimer
outer = QVBoxLayout(self)
outer.setContentsMargins(4, 4, 4, 4)
@@ -87,7 +90,9 @@ class SkyTab(QWidget):
self._table.setHorizontalHeaderLabels(_COL_HEADERS)
hdr = self._table.horizontalHeader()
hdr.setSectionResizeMode(QHeaderView.ResizeToContents)
hdr.setStretchLastSection(True)
hdr.setSectionResizeMode(_COL_MSG, QHeaderView.Fixed)
hdr.setStretchLastSection(False)
self._table.setColumnWidth(_COL_MSG, 36)
self._table.setEditTriggers(QTableWidget.NoEditTriggers)
self._table.setSelectionBehavior(QTableWidget.SelectRows)
self._table.setAlternatingRowColors(False)
@@ -193,12 +198,15 @@ class SkyTab(QWidget):
# ── Data update ───────────────────────────────────────────────────────────
def _on_sat_update(self, rid: str, sats: list):
selected = self._selected_rids()
for sat in sats:
key = (rid, sat.gnss_id, sat.sv_id)
self._store[key] = sat
if key not in self._trail:
self._trail[key] = deque(maxlen=_TRAIL_MAXLEN)
self._trail[key].append((sat.elevation, sat.azimuth))
if rid in selected:
self._highlight_row(key)
self._sky.update_data(self._visible_sats(), self._active_trails())
self._update_info()
@@ -219,6 +227,36 @@ class SkyTab(QWidget):
def _rebuild_table_from_store(self):
self._rebuild_table(self._visible_sats())
# ── Row highlight on message receive ─────────────────────────────────────
def _highlight_row(self, key):
try:
row = self._table_keys.index(key)
except ValueError:
return # row not in table yet (full rebuild pending)
item = self._table.item(row, _COL_MSG)
if item:
item.setText("")
t = self._hi_timers.get(key)
if t:
t.start(_MSG_HIGHLIGHT_MS)
else:
t = QTimer(self)
t.setSingleShot(True)
t.timeout.connect(lambda k=key, r=row: self._clear_highlight(k, r))
t.start(_MSG_HIGHLIGHT_MS)
self._hi_timers[key] = t
def _clear_highlight(self, key, row):
self._hi_timers.pop(key, None)
if row >= self._table.rowCount() or row >= len(self._table_keys):
return
if self._table_keys[row] != key:
return # row was reassigned during a full rebuild
item = self._table.item(row, _COL_MSG)
if item:
item.setText("")
# ── Table ─────────────────────────────────────────────────────────────────
def _rebuild_table(self, sats: list):
@@ -260,6 +298,10 @@ class SkyTab(QWidget):
self._table.setItem(row, 4, cell(f"{sat.cno:.1f}"))
self._table.setItem(row, 5, cell("" if sat.used_in_fix else ""))
self._table.setItem(row, 6, cell(rid))
msg_item = QTableWidgetItem("")
msg_item.setTextAlignment(Qt.AlignCenter)
msg_item.setBackground(brush)
self._table.setItem(row, _COL_MSG, msg_item)
self._table.setSortingEnabled(True)
vp.setUpdatesEnabled(True)