Clean push: Removed heavy files & added only latest snapshot

This commit is contained in:
2025-07-26 05:16:12 +05:30
commit acf84e8767
250 changed files with 58564 additions and 0 deletions

View File

@@ -0,0 +1,432 @@
"""
Icon Management System
=====================
Comprehensive icon system with SVG icons, Material Design icons,
and utility functions for the Traffic Monitoring Application.
Features:
- Material Design icon set
- SVG icon generation
- Icon theming and colorization
- Size variants and scaling
- Custom icon registration
"""
from PySide6.QtGui import QIcon, QPixmap, QPainter, QColor, QBrush, QPen
from PySide6.QtCore import Qt, QSize
from PySide6.QtSvg import QSvgRenderer
from typing import Dict, Optional, Tuple
import base64
from io import BytesIO
class IconTheme:
"""Icon theme management"""
# Icon colors for dark theme
PRIMARY = "#FFFFFF"
SECONDARY = "#B0B0B0"
ACCENT = "#00BCD4"
SUCCESS = "#4CAF50"
WARNING = "#FF9800"
ERROR = "#F44336"
INFO = "#2196F3"
class SVGIcons:
"""Collection of SVG icons as base64 encoded strings"""
# Navigation icons
HOME = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2l7 7v11h-4v-7h-6v7H5V9l7-7z"/>
</svg>
"""
PLAY = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M8 5v14l11-7z"/>
</svg>
"""
PAUSE = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M6 4h4v16H6V4zm8 0h4v16h-4V4z"/>
</svg>
"""
STOP = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M6 6h12v12H6z"/>
</svg>
"""
RECORD = """
<svg viewBox="0 0 24 24" fill="currentColor">
<circle cx="12" cy="12" r="8"/>
</svg>
"""
# Detection and monitoring icons
CAMERA = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 8.8c-2.1 0-3.8 1.7-3.8 3.8s1.7 3.8 3.8 3.8 3.8-1.7 3.8-3.8-1.7-3.8-3.8-3.8z"/>
<path d="M21 7h-3.4l-1.9-2.6c-.4-.5-.9-.8-1.6-.8H9.9c-.7 0-1.2.3-1.6.8L6.4 7H3c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2z"/>
</svg>
"""
MONITOR = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M21 3H3c-1.1 0-2 .9-2 2v11c0 1.1.9 2 2 2h6l-2 3v1h8v-1l-2-3h6c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 11H3V5h18v9z"/>
</svg>
"""
TRAFFIC_LIGHT = """
<svg viewBox="0 0 24 24" fill="currentColor">
<rect x="8" y="2" width="8" height="20" rx="4" stroke="currentColor" stroke-width="2" fill="none"/>
<circle cx="12" cy="7" r="2" fill="#F44336"/>
<circle cx="12" cy="12" r="2" fill="#FF9800"/>
<circle cx="12" cy="17" r="2" fill="#4CAF50"/>
</svg>
"""
VIOLATION = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2L1 21h22L12 2zm0 3.99L19.53 19H4.47L12 5.99zM11 16h2v2h-2v-2zm0-6h2v4h-2v-4z"/>
</svg>
"""
# Analytics and statistics icons
CHART_BAR = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M5 9v6h4V9H5zm6-4v10h4V5h-4zm6 6v4h4v-4h-4z"/>
</svg>
"""
CHART_LINE = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M3.5 18.49l6-6.01 4 4L22 6.92l-1.41-1.41-7.09 7.97-4-4L3 16.99l.5 1.5z"/>
</svg>
"""
CHART_PIE = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M11 2v20c-5.07-.5-9-4.79-9-10s3.93-9.5 9-10zm2.03 0v8.99H22c-.47-4.74-4.24-8.52-8.97-8.99zm0 11.01V22c4.74-.47 8.5-4.25 8.97-8.99h-8.97z"/>
</svg>
"""
DASHBOARD = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z"/>
</svg>
"""
# System and settings icons
SETTINGS = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z"/>
</svg>
"""
EXPORT = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2L8 8h3v8h2V8h3l-4-6zm7 7h-2v10H7V9H5v10c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V9z"/>
</svg>
"""
IMPORT = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 22L8 16h3V8h2v8h3l-4 6zm7-15h-2V5H7v2H5V5c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2v2z"/>
</svg>
"""
SAVE = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V6h10v3z"/>
</svg>
"""
# Status and alert icons
CHECK_CIRCLE = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
</svg>
"""
WARNING_CIRCLE = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
</svg>
"""
ERROR_CIRCLE = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"/>
</svg>
"""
INFO_CIRCLE = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
</svg>
"""
# Action icons
REFRESH = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/>
</svg>
"""
DELETE = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/>
</svg>
"""
EDIT = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/>
</svg>
"""
FILTER = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>
</svg>
"""
SEARCH = """
<svg viewBox="0 0 24 24" fill="currentColor">
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
</svg>
"""
class IconManager:
"""Manages icons for the application"""
def __init__(self):
self._icon_cache: Dict[str, QIcon] = {}
self.theme = IconTheme()
def get_icon(self, name: str, color: str = IconTheme.PRIMARY, size: int = 24) -> QIcon:
"""Get an icon by name with specified color and size"""
cache_key = f"{name}_{color}_{size}"
if cache_key in self._icon_cache:
return self._icon_cache[cache_key]
# Get SVG content
svg_content = getattr(SVGIcons, name.upper(), None)
if not svg_content:
return QIcon() # Return empty icon if not found
# Replace currentColor with specified color
svg_content = svg_content.replace('currentColor', color)
# Create icon from SVG
icon = self._create_icon_from_svg(svg_content, size)
self._icon_cache[cache_key] = icon
return icon
def _create_icon_from_svg(self, svg_content: str, size: int) -> QIcon:
"""Create QIcon from SVG content"""
# Create QSvgRenderer from SVG content
svg_bytes = svg_content.encode('utf-8')
renderer = QSvgRenderer(svg_bytes)
# Create pixmap
pixmap = QPixmap(size, size)
pixmap.fill(Qt.transparent)
# Paint SVG onto pixmap
painter = QPainter(pixmap)
renderer.render(painter)
painter.end()
return QIcon(pixmap)
def get_status_icon(self, status: str, size: int = 16) -> QIcon:
"""Get icon for specific status"""
status_map = {
'success': ('CHECK_CIRCLE', IconTheme.SUCCESS),
'warning': ('WARNING_CIRCLE', IconTheme.WARNING),
'error': ('ERROR_CIRCLE', IconTheme.ERROR),
'info': ('INFO_CIRCLE', IconTheme.INFO),
'violation': ('VIOLATION', IconTheme.ERROR),
'active': ('PLAY', IconTheme.SUCCESS),
'inactive': ('PAUSE', IconTheme.SECONDARY),
'recording': ('RECORD', IconTheme.ERROR)
}
icon_name, color = status_map.get(status, ('INFO_CIRCLE', IconTheme.INFO))
return self.get_icon(icon_name, color, size)
def get_action_icon(self, action: str, size: int = 20) -> QIcon:
"""Get icon for specific action"""
action_map = {
'play': 'PLAY',
'pause': 'PAUSE',
'stop': 'STOP',
'record': 'RECORD',
'settings': 'SETTINGS',
'export': 'EXPORT',
'import': 'IMPORT',
'save': 'SAVE',
'refresh': 'REFRESH',
'delete': 'DELETE',
'edit': 'EDIT',
'filter': 'FILTER',
'search': 'SEARCH'
}
icon_name = action_map.get(action, 'INFO_CIRCLE')
return self.get_icon(icon_name, IconTheme.PRIMARY, size)
def get_navigation_icon(self, view: str, size: int = 24) -> QIcon:
"""Get icon for navigation views"""
nav_map = {
'home': 'HOME',
'detection': 'CAMERA',
'violations': 'VIOLATION',
'analytics': 'DASHBOARD',
'export': 'EXPORT',
'monitor': 'MONITOR',
'chart': 'CHART_BAR'
}
icon_name = nav_map.get(view, 'HOME')
return self.get_icon(icon_name, IconTheme.ACCENT, size)
def create_colored_icon(self, base_icon: str, color: str, size: int = 24) -> QIcon:
"""Create a colored version of an icon"""
return self.get_icon(base_icon, color, size)
def set_theme_color(self, color: str):
"""Set the theme accent color"""
self.theme.ACCENT = color
# Clear cache to regenerate icons with new color
self._icon_cache.clear()
# Global icon manager instance
icon_manager = IconManager()
# Convenience functions
def get_icon(name: str, color: str = IconTheme.PRIMARY, size: int = 24) -> QIcon:
"""Get an icon - convenience function"""
return icon_manager.get_icon(name, color, size)
def get_status_icon(status: str, size: int = 16) -> QIcon:
"""Get status icon - convenience function"""
return icon_manager.get_status_icon(status, size)
def get_action_icon(action: str, size: int = 20) -> QIcon:
"""Get action icon - convenience function"""
return icon_manager.get_action_icon(action, size)
def get_navigation_icon(view: str, size: int = 24) -> QIcon:
"""Get navigation icon - convenience function"""
return icon_manager.get_navigation_icon(view, size)
# Common icon sets for easy access
class CommonIcons:
"""Commonly used icon combinations"""
@staticmethod
def toolbar_icons() -> Dict[str, QIcon]:
"""Get all toolbar icons"""
return {
'play': get_action_icon('play'),
'pause': get_action_icon('pause'),
'stop': get_action_icon('stop'),
'record': get_action_icon('record'),
'settings': get_action_icon('settings'),
'export': get_action_icon('export'),
'refresh': get_action_icon('refresh')
}
@staticmethod
def status_icons() -> Dict[str, QIcon]:
"""Get all status icons"""
return {
'success': get_status_icon('success'),
'warning': get_status_icon('warning'),
'error': get_status_icon('error'),
'info': get_status_icon('info'),
'violation': get_status_icon('violation'),
'active': get_status_icon('active'),
'inactive': get_status_icon('inactive'),
'recording': get_status_icon('recording')
}
@staticmethod
def navigation_icons() -> Dict[str, QIcon]:
"""Get all navigation icons"""
return {
'detection': get_navigation_icon('detection'),
'violations': get_navigation_icon('violations'),
'analytics': get_navigation_icon('analytics'),
'export': get_navigation_icon('export'),
'monitor': get_navigation_icon('monitor')
}
# Traffic light specific icons
def create_traffic_light_icon(red_on: bool = False, yellow_on: bool = False, green_on: bool = False, size: int = 32) -> QIcon:
"""Create a traffic light icon with specific lights on/off"""
svg_template = f"""
<svg viewBox="0 0 24 24" width="{size}" height="{size}">
<rect x="8" y="2" width="8" height="20" rx="4" stroke="#424242" stroke-width="2" fill="#2C2C2C"/>
<circle cx="12" cy="7" r="2" fill="{'#F44336' if red_on else '#5D4037'}"/>
<circle cx="12" cy="12" r="2" fill="{'#FF9800' if yellow_on else '#5D4037'}"/>
<circle cx="12" cy="17" r="2" fill="{'#4CAF50' if green_on else '#5D4037'}"/>
</svg>
"""
svg_bytes = svg_template.encode('utf-8')
renderer = QSvgRenderer(svg_bytes)
pixmap = QPixmap(size, size)
pixmap.fill(Qt.transparent)
painter = QPainter(pixmap)
renderer.render(painter)
painter.end()
return QIcon(pixmap)
# New FinaleIcons class to wrap the existing functionality
class FinaleIcons:
"""
Wrapper class for icon management to maintain compatibility
with existing code that references FinaleIcons.get_icon() etc.
"""
@staticmethod
def get_icon(name: str, color: str = IconTheme.PRIMARY, size: int = 24) -> QIcon:
"""Get an icon by name"""
return get_icon(name, color, size)
@staticmethod
def get_status_icon(status: str, size: int = 16) -> QIcon:
"""Get a status icon"""
return get_status_icon(status, size)
@staticmethod
def get_action_icon(action: str, size: int = 20) -> QIcon:
"""Get an action icon"""
return get_action_icon(action, size)
@staticmethod
def get_navigation_icon(view: str, size: int = 24) -> QIcon:
"""Get a navigation icon"""
return get_navigation_icon(view, size)
@staticmethod
def create_colored_icon(base_icon: str, color: str, size: int = 24) -> QIcon:
"""Create a colored version of an icon"""
return get_icon(base_icon, color, size)
@staticmethod
def traffic_light_icon(red_on: bool = False, yellow_on: bool = False, green_on: bool = False, size: int = 32) -> QIcon:
"""Create a traffic light icon with specific lights on/off"""
return create_traffic_light_icon(red_on, yellow_on, green_on, size)