Multi-iPad dest_id routing, activity ring, context menu hide, live label/visibility sync

Desktop:
- Replace Remote checkbox with T: dest_spin (0=Off, 1-9=tablet) on all widgets
- dest_id persisted in get_state/set_state, broadcast in tablet snapshot
- dest_spin.valueChanged triggers save + broadcast to iPad
- _on_widget_visibility_from_tablet updates dest_spin from iPad hide event
- _broadcast_preset_update shared helper; ws_server.has_clients guard
- label editingFinished triggers live label sync to iPad

iOS:
- VC-Arrange/VC-Logging/Widgets-Reusable-UI file reorganisation
- ArrangeObjects/ArrangeView rename, 7-bucket Arrange-Functions split
- myTabletId (UserDefaults) + tabletIdField next to port in toolbar
- Preset filter: destId == myTabletId instead of visible bool
- BaseWidget activity ring: long press gesture (touch) + final update() flash
- Context menu long press (arrange mode): hide widget, save layout, send dest_id:0
- Same-UUID preset check skips Preset Switched alert on visibility/label updates
- autoSwitchEnabled, toolbarStatusLabel, presetLabel, statusToken

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Paul Lipscomb
2026-07-02 21:56:35 -04:00
parent 7a74cfa75e
commit d6201c59b4
32 changed files with 1042 additions and 501 deletions
+15 -2
View File
@@ -2,7 +2,7 @@ import uuid
from PyQt6.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout, QPushButton,
QLabel, QSpinBox, QLineEdit, QFrame, QSizePolicy
QLabel, QSpinBox, QLineEdit, QFrame, QSizePolicy, QCheckBox
)
from PyQt6.QtCore import Qt, QEvent, QTimer
@@ -195,6 +195,15 @@ class TransportWidget(QWidget):
btn_row.addWidget(self.plus_btn)
inner.addLayout(btn_row)
# Remote checkbox
self.dest_spin = QSpinBox()
self.dest_spin.setRange(0, 9)
self.dest_spin.setSpecialValueText("Off")
self.dest_spin.setPrefix("T:")
self.dest_spin.setValue(1)
self.dest_spin.setFixedWidth(52)
inner.addWidget(self.dest_spin, alignment=Qt.AlignmentFlag.AlignHCenter)
# Zone button
self.zone_btn = ZoneButton()
self.zone_btn.left_callback = lambda active: self.on_zone_checked("left", active)
@@ -378,6 +387,7 @@ class TransportWidget(QWidget):
"output_mode": self.output_mode,
"osc_addr": self.osc_addr_edit.text(),
"trigger_mode": self.trigger_mode,
"dest_id": self.dest_spin.value(),
}
def set_state(self, state):
@@ -403,4 +413,7 @@ class TransportWidget(QWidget):
self.cc_input_lbl.setStyleSheet("background-color: #000000; color: #00e676; font-size: 10px; padding: 1px;")
self.osc_addr_edit.setText(state.get("osc_addr", "/play"))
self.set_output_mode(state.get("output_mode", "midi"))
self.set_trigger_mode(state.get("trigger_mode", "momentary"))
self.set_trigger_mode(state.get("trigger_mode", "momentary"))
self.dest_spin.blockSignals(True)
self.dest_spin.setValue(state.get("dest_id", 1))
self.dest_spin.blockSignals(False)