""" User Guide Tab - Help documentation viewer """ from PySide6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QTextBrowser, QComboBox, QLabel, QPushButton, QSplitter, QTreeWidget, QTreeWidgetItem, QMessageBox ) from PySide6.QtCore import Qt, Signal, QUrl from PySide6.QtGui import QFont, QPixmap import os import markdown from pathlib import Path class UserGuideTab(QWidget): """User Guide tab for displaying help documentation""" def __init__(self): super().__init__() self.docs_path = Path(__file__).parent.parent / "docs" / "user-guide" self.setup_ui() self.load_documentation() def setup_ui(self): """Setup the user interface""" layout = QVBoxLayout(self) # Header header_layout = QHBoxLayout() # Title title_label = QLabel("📚 User Guide & Documentation") title_font = QFont() title_font.setPointSize(14) title_font.setBold(True) title_label.setFont(title_font) # Document selector self.doc_selector = QComboBox() self.doc_selector.setMinimumWidth(250) self.doc_selector.currentTextChanged.connect(self.load_selected_document) # Refresh button refresh_btn = QPushButton("🔄 Refresh") refresh_btn.clicked.connect(self.load_documentation) header_layout.addWidget(title_label) header_layout.addStretch() header_layout.addWidget(QLabel("Select Document:")) header_layout.addWidget(self.doc_selector) header_layout.addWidget(refresh_btn) layout.addLayout(header_layout) # Main content area splitter = QSplitter(Qt.Horizontal) # Navigation tree (left panel) self.nav_tree = QTreeWidget() self.nav_tree.setHeaderLabel("Documentation") self.nav_tree.setMaximumWidth(250) self.nav_tree.itemClicked.connect(self.on_nav_item_clicked) # Content viewer (right panel) self.content_viewer = QTextBrowser() self.content_viewer.setOpenExternalLinks(True) splitter.addWidget(self.nav_tree) splitter.addWidget(self.content_viewer) splitter.setSizes([250, 800]) layout.addWidget(splitter) # Status bar status_layout = QHBoxLayout() self.status_label = QLabel("Ready") status_layout.addWidget(self.status_label) status_layout.addStretch() layout.addLayout(status_layout) def load_documentation(self): """Load available documentation files""" try: self.doc_selector.clear() self.nav_tree.clear() if not self.docs_path.exists(): self.content_viewer.setHtml( "

📚 Documentation

" "

No documentation directory found. Creating default documentation...

" ) self.create_default_docs() return # Find all markdown files md_files = list(self.docs_path.glob("*.md")) if not md_files: self.content_viewer.setHtml( "

📚 Documentation

" "

No documentation files found in the user-guide directory.

" ) return # Populate document selector for md_file in sorted(md_files): display_name = self.format_filename(md_file.stem) self.doc_selector.addItem(display_name, md_file) # Populate navigation tree self.populate_nav_tree(md_files) # Load first document if md_files: self.load_document(md_files[0]) self.status_label.setText(f"Loaded {len(md_files)} documentation files") except Exception as e: self.show_error(f"Error loading documentation: {e}") def populate_nav_tree(self, md_files): """Populate the navigation tree""" categories = { "Getting Started": [], "Smart Intersection": [], "Configuration": [], "Troubleshooting": [], "Other": [] } # Categorize files for md_file in md_files: filename = md_file.stem.lower() if any(word in filename for word in ['start', 'getting', 'intro', 'overview']): categories["Getting Started"].append(md_file) elif any(word in filename for word in ['smart', 'intersection', 'scene']): categories["Smart Intersection"].append(md_file) elif any(word in filename for word in ['config', 'setup', 'settings']): categories["Configuration"].append(md_file) elif any(word in filename for word in ['trouble', 'support', 'help', 'error']): categories["Troubleshooting"].append(md_file) else: categories["Other"].append(md_file) # Add to tree for category, files in categories.items(): if files: category_item = QTreeWidgetItem(self.nav_tree, [category]) category_item.setExpanded(True) for md_file in sorted(files): file_item = QTreeWidgetItem(category_item, [self.format_filename(md_file.stem)]) file_item.setData(0, Qt.UserRole, md_file) def format_filename(self, filename): """Format filename for display""" # Convert kebab-case to title case return filename.replace('-', ' ').replace('_', ' ').title() def on_nav_item_clicked(self, item, column): """Handle navigation tree item click""" file_path = item.data(0, Qt.UserRole) if file_path and isinstance(file_path, Path): self.load_document(file_path) # Update selector for i in range(self.doc_selector.count()): if self.doc_selector.itemData(i) == file_path: self.doc_selector.setCurrentIndex(i) break def load_selected_document(self, display_name): """Load document selected from dropdown""" current_index = self.doc_selector.currentIndex() if current_index >= 0: file_path = self.doc_selector.itemData(current_index) if file_path: self.load_document(file_path) def load_document(self, file_path): """Load and display a markdown document""" try: if not file_path.exists(): self.content_viewer.setHtml(f"

File not found: {file_path}

") return # Read markdown content with open(file_path, 'r', encoding='utf-8') as f: md_content = f.read() # Convert to HTML html_content = markdown.markdown( md_content, extensions=['toc', 'codehilite', 'fenced_code', 'tables'] ) # Add CSS styling styled_html = self.add_css_styling(html_content) # Display in browser self.content_viewer.setHtml(styled_html) self.status_label.setText(f"Loaded: {file_path.name}") except Exception as e: self.show_error(f"Error loading document {file_path.name}: {e}") def add_css_styling(self, html_content): """Add CSS styling to HTML content""" css = """ """ return f"{css}{html_content}" def create_default_docs(self): """Create default documentation if none exists""" try: self.docs_path.mkdir(parents=True, exist_ok=True) # Create a basic getting started document getting_started = """# Getting Started with Traffic Monitoring Desktop App ## Overview Welcome to the Traffic Monitoring Desktop Application with Smart Intersection Analytics. ## Key Features - **Real-time Detection**: YOLO-based object detection with Intel Arc GPU acceleration - **Multi-camera Support**: Process multiple camera feeds simultaneously - **Scene Analytics**: Smart intersection analytics for traffic monitoring - **VLM Insights**: Vision Language Model for contextual understanding - **Local Processing**: All processing happens locally with no cloud dependency ## Quick Start 1. Launch the application: `python main.py` 2. Configure your cameras in the Config tab 3. Start live detection in the Live Detection tab 4. View analytics in the Analytics tab 5. Access insights through the VLM panel ## Support For help and troubleshooting, check the other documentation sections or contact support. """ with open(self.docs_path / "getting-started.md", 'w', encoding='utf-8') as f: f.write(getting_started) self.load_documentation() except Exception as e: self.show_error(f"Error creating default documentation: {e}") def show_error(self, message): """Show error message""" self.content_viewer.setHtml(f"

Error

{message}

") self.status_label.setText("Error occurred") # Also show message box for critical errors QMessageBox.warning(self, "Documentation Error", message)