The Insights Menu is a PySide6 window that launches automatically when the race replay starts. It provides quick access to telemetry analysis tools and insight windows. The menu stays open alongside the replay and allows you to launch multiple insight windows.
- Example Insight Window - A working example demonstrating the PitWallWindow pattern
- Telemetry Stream Viewer - View raw telemetry data in real-time
The menu launches automatically when you start a race replay and open a "Race" session.
To add a new insight button to the menu, follow these steps:
First, create your insight window using the PitWallWindow base class:
# src/gui/my_custom_insight.py
from src.gui.pit_wall_window import PitWallWindow
from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel
class MyCustomInsight(PitWallWindow):
"""My custom telemetry insight."""
def setup_ui(self):
"""Create the custom UI."""
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
self.data_label = QLabel("Waiting for data...")
layout.addWidget(self.data_label)
def on_telemetry_data(self, data):
"""Process incoming telemetry data."""
# Your data processing logic
self.data_label.setText(f"Latest data: {data}")
def on_stream_error(self, error_msg):
"""Handle errors."""
self.data_label.setText(f"Error: {error_msg}")In src/gui/insights_menu.py, add a launch method for your insight:
def launch_my_custom_insight(self):
"""Launch my custom insight window."""
print("π Launching: My Custom Insight")
from src.gui.my_custom_insight import MyCustomInsight
window = MyCustomInsight()
window.show()
self.opened_windows.append(window)In the setup_ui() method of InsightsMenu, add your button to an existing category or create a new one:
Adding to an existing category:
content_layout.addWidget(self.create_category_section(
"Live Telemetry",
[
("Telemetry Stream Viewer", "View raw telemetry data", self.launch_telemetry_viewer),
("My Custom Insight", "Description of what it does", self.launch_my_custom_insight), # Add here
]
))Creating a new category:
content_layout.addWidget(self.create_category_section(
"Custom Analysis",
[
("My Custom Insight", "Description of what it does", self.launch_my_custom_insight),
]
))Run the menu standalone to test your new button:
python -m src.gui.insights_menuThis will open the Insights Menu without starting a replay. The window wouldn't be connected to telemetry unless you start a replay, but you can verify that the button launches your insight window correctly.s
InsightsMenu (QMainWindow)
βββ Header
β βββ Title: "ποΈ F1 Insights"
β βββ Subtitle: "Launch telemetry insights and analysis tools"
βββ Scrollable Content (QScrollArea)
β βββ Category Section 1
β β βββ Category Label (e.g., "EXAMPLE INSIGHTS")
β β βββ Separator Line
β β βββ Insight Button 1 (name + description)
β β βββ Insight Button 2
β β βββ ...
β βββ Category Section 2
β β βββ ...
β βββ Stretch (pushes footer to bottom)
βββ Footer
βββ Info Label: "Requires telemetry stream enabled"
βββ Close Menu Button
create_category_section(category_name, insights)
- Creates a category section with multiple insight buttons
insights: List of tuples(name, description, callback)- Each tuple becomes a clickable button
create_insight_button(name, description, callback)
- Creates a styled button with bold name and smaller description
- Minimum height: 50px
- Connects the button to the launch callback
opened_windows list
- Keeps references to all launched insight windows
- Prevents Python from garbage collecting active windows
- Windows remain open even if menu is closed
- User starts replay with
python main.py --viewer main.pycallslaunch_insights_menu()fromsrc.run_session- Menu window is created and shown
- User clicks insight buttons to open analysis windows
- Each insight launches in its own window with independent telemetry connection
The menu uses inline stylesheets (no external CSS). The default theme is dark with minimal styling:
- Background: Dark (inherits from system theme)
- Font: Arial at various sizes (24pt title, 12pt buttons, 10pt descriptions)
- Buttons: Minimum 50px height with name and description
- Cursor: Pointing hand cursor on buttons
To customize the appearance, edit the setup_ui() method and add a stylesheet:
self.setStyleSheet("""
QMainWindow {
background-color: #1e1e1e;
}
QPushButton {
background-color: #2d2d2d;
border: 1px solid #3d3d3d;
border-radius: 4px;
padding: 8px;
}
QPushButton:hover {
border: 1px solid #e10600; /* Ferrari red */
background-color: #3d3d3d;
}
""")Adjust in __init__():
self.setGeometry(50, 50, 300, 600) # x, y, width, heightModify create_insight_button() to customize buttons:
def create_insight_button(self, name, description, callback):
button = QPushButton()
# Custom layout
btn_layout = QVBoxLayout()
name_label = QLabel(name)
name_label.setFont(QFont("Arial", 14, QFont.Bold)) # Larger font
desc_label = QLabel(description)
desc_label.setFont(QFont("Arial", 9, QFont.Italic)) # Italic description
btn_layout.addWidget(name_label)
btn_layout.addWidget(desc_label)
button.setLayout(btn_layout)
button.setMinimumHeight(60) # Taller buttons
button.clicked.connect(callback)
return button- PitWallWindow.md - Base class for creating insights
- ../src/gui/insights_menu.py - Menu implementation
- ../src/gui/example_pit_wall_window.py - Example insight
