Clean push: Removed heavy files & added only latest snapshot
This commit is contained in:
360
qt_app_pyside1/ui/export_tab.py
Normal file
360
qt_app_pyside1/ui/export_tab.py
Normal file
@@ -0,0 +1,360 @@
|
||||
from PySide6.QtWidgets import (
|
||||
QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QFileDialog,
|
||||
QPlainTextEdit, QGroupBox, QLabel, QComboBox, QCheckBox,
|
||||
QTableWidget, QTableWidgetItem, QFormLayout, QLineEdit,
|
||||
QDateTimeEdit, QSpinBox, QTabWidget, QStyle
|
||||
)
|
||||
from PySide6.QtCore import Qt, Slot, QDateTime
|
||||
from PySide6.QtGui import QFont
|
||||
|
||||
class ConfigSection(QGroupBox):
|
||||
"""Configuration editor section"""
|
||||
|
||||
def __init__(self, title):
|
||||
super().__init__(title)
|
||||
self.layout = QVBoxLayout(self)
|
||||
|
||||
class ExportTab(QWidget):
|
||||
"""Tab for exporting data and managing configuration."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.initUI()
|
||||
|
||||
def initUI(self):
|
||||
"""Initialize UI components"""
|
||||
main_layout = QVBoxLayout(self)
|
||||
|
||||
# Create tab widget for organizing export and config sections
|
||||
tab_widget = QTabWidget()
|
||||
|
||||
# Tab 1: Export Data
|
||||
export_tab = QWidget()
|
||||
export_layout = QVBoxLayout(export_tab)
|
||||
|
||||
# Export options
|
||||
export_options = QGroupBox("Export Options")
|
||||
options_layout = QFormLayout(export_options)
|
||||
|
||||
self.export_format_combo = QComboBox()
|
||||
self.export_format_combo.addItems(["CSV", "JSON", "Excel", "PDF Report"])
|
||||
|
||||
self.export_data_combo = QComboBox()
|
||||
self.export_data_combo.addItems([
|
||||
"All Data",
|
||||
"Detections Only",
|
||||
"Violations Only",
|
||||
"Analytics Summary"
|
||||
])
|
||||
|
||||
# Time range
|
||||
time_layout = QHBoxLayout()
|
||||
self.export_range_check = QCheckBox("Time Range:")
|
||||
self.export_range_check.setChecked(False)
|
||||
|
||||
self.export_start_time = QDateTimeEdit(QDateTime.currentDateTime().addDays(-1))
|
||||
self.export_start_time.setEnabled(False)
|
||||
self.export_end_time = QDateTimeEdit(QDateTime.currentDateTime())
|
||||
self.export_end_time.setEnabled(False)
|
||||
|
||||
self.export_range_check.toggled.connect(self.export_start_time.setEnabled)
|
||||
self.export_range_check.toggled.connect(self.export_end_time.setEnabled)
|
||||
|
||||
time_layout.addWidget(self.export_range_check)
|
||||
time_layout.addWidget(self.export_start_time)
|
||||
time_layout.addWidget(QLabel("to"))
|
||||
time_layout.addWidget(self.export_end_time)
|
||||
|
||||
options_layout.addRow("Export Format:", self.export_format_combo)
|
||||
options_layout.addRow("Data to Export:", self.export_data_combo)
|
||||
options_layout.addRow(time_layout)
|
||||
|
||||
# Include options
|
||||
include_layout = QHBoxLayout()
|
||||
self.include_images_check = QCheckBox("Include Images")
|
||||
self.include_images_check.setChecked(True)
|
||||
self.include_analytics_check = QCheckBox("Include Analytics")
|
||||
self.include_analytics_check.setChecked(True)
|
||||
|
||||
include_layout.addWidget(self.include_images_check)
|
||||
include_layout.addWidget(self.include_analytics_check)
|
||||
options_layout.addRow("Include:", include_layout)
|
||||
|
||||
export_layout.addWidget(export_options)
|
||||
# Export preview
|
||||
preview_box = QGroupBox("Export Preview")
|
||||
preview_layout = QVBoxLayout(preview_box)
|
||||
self.export_preview = QTableWidget(5, 3)
|
||||
self.export_preview.setHorizontalHeaderLabels(["Type", "Count", "Details"])
|
||||
self.export_preview.setAlternatingRowColors(True)
|
||||
self.export_preview.setEditTriggers(QTableWidget.NoEditTriggers)
|
||||
|
||||
# Initialize table items with default values
|
||||
self.export_preview.setItem(0, 0, QTableWidgetItem("Vehicles"))
|
||||
self.export_preview.setItem(0, 1, QTableWidgetItem("0"))
|
||||
self.export_preview.setItem(0, 2, QTableWidgetItem("Cars, trucks, buses"))
|
||||
|
||||
self.export_preview.setItem(1, 0, QTableWidgetItem("Pedestrians"))
|
||||
self.export_preview.setItem(1, 1, QTableWidgetItem("0"))
|
||||
self.export_preview.setItem(1, 2, QTableWidgetItem("People detected"))
|
||||
|
||||
self.export_preview.setItem(2, 0, QTableWidgetItem("Red Light Violations"))
|
||||
self.export_preview.setItem(2, 1, QTableWidgetItem("0"))
|
||||
self.export_preview.setItem(2, 2, QTableWidgetItem("Vehicles running red lights"))
|
||||
|
||||
self.export_preview.setItem(3, 0, QTableWidgetItem("Stop Sign Violations"))
|
||||
self.export_preview.setItem(3, 1, QTableWidgetItem("0"))
|
||||
self.export_preview.setItem(3, 2, QTableWidgetItem("Vehicles ignoring stop signs"))
|
||||
|
||||
self.export_preview.setItem(4, 0, QTableWidgetItem("Speed Violations"))
|
||||
self.export_preview.setItem(4, 1, QTableWidgetItem("0"))
|
||||
self.export_preview.setItem(4, 2, QTableWidgetItem("Vehicles exceeding speed limits"))
|
||||
|
||||
preview_layout.addWidget(self.export_preview)
|
||||
export_layout.addWidget(preview_box)
|
||||
|
||||
# Export buttons
|
||||
export_buttons = QHBoxLayout()
|
||||
self.export_btn = QPushButton("Export Data")
|
||||
self.export_btn.setIcon(self.style().standardIcon(QStyle.SP_DialogSaveButton))
|
||||
self.clear_export_btn = QPushButton("Clear Data")
|
||||
export_buttons.addWidget(self.export_btn)
|
||||
export_buttons.addWidget(self.clear_export_btn)
|
||||
export_layout.addLayout(export_buttons)
|
||||
|
||||
tab_widget.addTab(export_tab, "Export Data")
|
||||
|
||||
# Tab 2: Configuration
|
||||
config_tab = QWidget()
|
||||
config_layout = QVBoxLayout(config_tab)
|
||||
|
||||
# Detection configuration
|
||||
detection_config = ConfigSection("Detection Configuration")
|
||||
detection_form = QFormLayout()
|
||||
|
||||
self.conf_threshold = QSpinBox()
|
||||
self.conf_threshold.setRange(1, 100)
|
||||
self.conf_threshold.setValue(50)
|
||||
self.conf_threshold.setSuffix("%")
|
||||
|
||||
self.enable_tracking = QCheckBox()
|
||||
self.enable_tracking.setChecked(True)
|
||||
|
||||
self.model_path = QLineEdit()
|
||||
self.model_path.setPlaceholderText("Path to model file")
|
||||
self.browse_model_btn = QPushButton("Browse...")
|
||||
model_layout = QHBoxLayout()
|
||||
model_layout.addWidget(self.model_path)
|
||||
model_layout.addWidget(self.browse_model_btn)
|
||||
|
||||
detection_form.addRow("Confidence Threshold:", self.conf_threshold)
|
||||
detection_form.addRow("Enable Tracking:", self.enable_tracking)
|
||||
detection_form.addRow("Model Path:", model_layout)
|
||||
|
||||
detection_config.layout.addLayout(detection_form)
|
||||
|
||||
# Violation configuration
|
||||
violation_config = ConfigSection("Violation Configuration")
|
||||
violation_form = QFormLayout()
|
||||
|
||||
self.red_light_grace = QSpinBox()
|
||||
self.red_light_grace.setRange(0, 10)
|
||||
self.red_light_grace.setValue(2)
|
||||
self.red_light_grace.setSuffix(" sec")
|
||||
|
||||
self.stop_sign_duration = QSpinBox()
|
||||
self.stop_sign_duration.setRange(0, 10)
|
||||
self.stop_sign_duration.setValue(2)
|
||||
self.stop_sign_duration.setSuffix(" sec")
|
||||
|
||||
self.speed_tolerance = QSpinBox()
|
||||
self.speed_tolerance.setRange(0, 20)
|
||||
self.speed_tolerance.setValue(5)
|
||||
self.speed_tolerance.setSuffix(" km/h")
|
||||
|
||||
violation_form.addRow("Red Light Grace Period:", self.red_light_grace)
|
||||
violation_form.addRow("Stop Sign Duration:", self.stop_sign_duration)
|
||||
violation_form.addRow("Speed Tolerance:", self.speed_tolerance)
|
||||
|
||||
violation_config.layout.addLayout(violation_form)
|
||||
|
||||
# Display configuration
|
||||
display_config = ConfigSection("Display Configuration")
|
||||
display_form = QFormLayout()
|
||||
|
||||
self.show_labels = QCheckBox()
|
||||
self.show_labels.setChecked(True)
|
||||
|
||||
self.show_confidence = QCheckBox()
|
||||
self.show_confidence.setChecked(True)
|
||||
|
||||
self.max_display_width = QSpinBox()
|
||||
self.max_display_width.setRange(320, 4096)
|
||||
self.max_display_width.setValue(800)
|
||||
self.max_display_width.setSingleStep(10)
|
||||
self.max_display_width.setSuffix(" px")
|
||||
|
||||
display_form.addRow("Show Labels:", self.show_labels)
|
||||
display_form.addRow("Show Confidence:", self.show_confidence)
|
||||
display_form.addRow("Max Display Width:", self.max_display_width)
|
||||
|
||||
display_config.layout.addLayout(display_form)
|
||||
|
||||
# Add config sections
|
||||
config_layout.addWidget(detection_config)
|
||||
config_layout.addWidget(violation_config)
|
||||
config_layout.addWidget(display_config)
|
||||
|
||||
# Config buttons
|
||||
config_buttons = QHBoxLayout()
|
||||
self.save_config_btn = QPushButton("Save Configuration")
|
||||
self.save_config_btn.setIcon(self.style().standardIcon(QStyle.SP_DialogSaveButton))
|
||||
self.reload_config_btn = QPushButton("Reload Configuration")
|
||||
self.reload_config_btn.setIcon(self.style().standardIcon(QStyle.SP_BrowserReload))
|
||||
|
||||
self.reset_btn = QPushButton("Reset Defaults")
|
||||
self.reset_btn.setIcon(self.style().standardIcon(QStyle.SP_DialogResetButton))
|
||||
|
||||
config_buttons.addWidget(self.save_config_btn)
|
||||
config_buttons.addWidget(self.reload_config_btn)
|
||||
config_buttons.addWidget(self.reset_btn)
|
||||
config_layout.addLayout(config_buttons)
|
||||
|
||||
# Raw config editor
|
||||
raw_config = QGroupBox("Raw Configuration (JSON)")
|
||||
raw_layout = QVBoxLayout(raw_config)
|
||||
|
||||
self.config_editor = QPlainTextEdit()
|
||||
self.config_editor.setFont(QFont("Consolas", 10))
|
||||
raw_layout.addWidget(self.config_editor)
|
||||
|
||||
config_layout.addWidget(raw_config)
|
||||
|
||||
tab_widget.addTab(config_tab, "Configuration")
|
||||
|
||||
main_layout.addWidget(tab_widget)
|
||||
|
||||
@Slot()
|
||||
def browse_model_path(self):
|
||||
"""Browse for model file"""
|
||||
file_path, _ = QFileDialog.getOpenFileName(
|
||||
self,
|
||||
"Select Model File",
|
||||
"",
|
||||
"Model Files (*.xml *.bin *.pt *.pth);;All Files (*)"
|
||||
)
|
||||
|
||||
if file_path:
|
||||
self.model_path.setText(file_path)
|
||||
|
||||
@Slot(dict)
|
||||
def update_export_preview(self, analytics):
|
||||
"""
|
||||
Update export preview with analytics data.
|
||||
|
||||
Args:
|
||||
analytics: Dictionary of analytics data
|
||||
"""
|
||||
if not analytics:
|
||||
return
|
||||
|
||||
# Update detection counts
|
||||
detection_counts = analytics.get('detection_counts', {})
|
||||
vehicle_count = sum([
|
||||
detection_counts.get('car', 0),
|
||||
detection_counts.get('truck', 0),
|
||||
detection_counts.get('bus', 0),
|
||||
detection_counts.get('motorcycle', 0)
|
||||
])
|
||||
pedestrian_count = detection_counts.get('person', 0)
|
||||
|
||||
# Update violation counts
|
||||
violation_counts = analytics.get('violation_counts', {})
|
||||
red_light_count = violation_counts.get('red_light_violation', 0)
|
||||
stop_sign_count = violation_counts.get('stop_sign_violation', 0)
|
||||
speed_count = violation_counts.get('speed_violation', 0)
|
||||
# Update table - create items if they don't exist
|
||||
item_data = [
|
||||
(0, "Vehicles", vehicle_count, "Cars, trucks, buses"),
|
||||
(1, "Pedestrians", pedestrian_count, "People detected"),
|
||||
(2, "Red Light Violations", red_light_count, "Vehicles running red lights"),
|
||||
(3, "Stop Sign Violations", stop_sign_count, "Vehicles ignoring stop signs"),
|
||||
(4, "Speed Violations", speed_count, "Vehicles exceeding speed limits")
|
||||
]
|
||||
|
||||
for row, label, count, details in item_data:
|
||||
# Check and create Type column item
|
||||
if self.export_preview.item(row, 0) is None:
|
||||
self.export_preview.setItem(row, 0, QTableWidgetItem(label))
|
||||
|
||||
# Check and create or update Count column item
|
||||
if self.export_preview.item(row, 1) is None:
|
||||
self.export_preview.setItem(row, 1, QTableWidgetItem(str(count)))
|
||||
else:
|
||||
self.export_preview.item(row, 1).setText(str(count))
|
||||
|
||||
# Check and create Details column item
|
||||
if self.export_preview.item(row, 2) is None:
|
||||
self.export_preview.setItem(row, 2, QTableWidgetItem(details))
|
||||
|
||||
@Slot(dict)
|
||||
def update_config_display(self, config):
|
||||
"""
|
||||
Update configuration display.
|
||||
|
||||
Args:
|
||||
config: Configuration dictionary
|
||||
"""
|
||||
if not config:
|
||||
return
|
||||
|
||||
# Convert to JSON for display
|
||||
import json
|
||||
self.config_editor.setPlainText(
|
||||
json.dumps(config, indent=2)
|
||||
)
|
||||
|
||||
# Update form fields
|
||||
detection_config = config.get('detection', {})
|
||||
self.conf_threshold.setValue(int(detection_config.get('confidence_threshold', 0.5) * 100))
|
||||
self.enable_tracking.setChecked(detection_config.get('enable_tracking', True))
|
||||
|
||||
if detection_config.get('model_path'):
|
||||
self.model_path.setText(detection_config.get('model_path'))
|
||||
|
||||
violation_config = config.get('violations', {})
|
||||
self.red_light_grace.setValue(violation_config.get('red_light_grace_period', 2))
|
||||
self.stop_sign_duration.setValue(violation_config.get('stop_sign_duration', 2))
|
||||
self.speed_tolerance.setValue(violation_config.get('speed_tolerance', 5))
|
||||
|
||||
display_config = config.get('display', {})
|
||||
self.show_labels.setChecked(display_config.get('show_labels', True))
|
||||
self.show_confidence.setChecked(display_config.get('show_confidence', True))
|
||||
self.max_display_width.setValue(display_config.get('max_display_width', 800))
|
||||
|
||||
def get_config_from_ui(self):
|
||||
"""
|
||||
Get configuration from UI fields.
|
||||
|
||||
Returns:
|
||||
Configuration dictionary
|
||||
"""
|
||||
config = {
|
||||
'detection': {
|
||||
'confidence_threshold': self.conf_threshold.value() / 100.0,
|
||||
'enable_tracking': self.enable_tracking.isChecked(),
|
||||
'model_path': self.model_path.text() if self.model_path.text() else None
|
||||
},
|
||||
'violations': {
|
||||
'red_light_grace_period': self.red_light_grace.value(),
|
||||
'stop_sign_duration': self.stop_sign_duration.value(),
|
||||
'speed_tolerance': self.speed_tolerance.value()
|
||||
},
|
||||
'display': {
|
||||
'max_display_width': self.max_display_width.value(),
|
||||
'show_confidence': self.show_confidence.isChecked(),
|
||||
'show_labels': self.show_labels.isChecked()
|
||||
}
|
||||
}
|
||||
|
||||
return config
|
||||
Reference in New Issue
Block a user