EU-Utility/premium/widgets/metrics_card.py

122 lines
3.4 KiB
Python

"""
Metrics card widget for displaying statistics.
"""
from typing import List, Optional
from dataclasses import dataclass
try:
from PyQt6.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout, QLabel, QGridLayout
)
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QFont
HAS_QT = True
except ImportError:
HAS_QT = False
QWidget = object
@dataclass
class StatItem:
"""Single statistic item."""
label: str
value: str
change: Optional[str] = None
positive: bool = True
class MetricsCard(QWidget if HAS_QT else object):
"""Card displaying multiple metrics."""
def __init__(self, title: str = "Metrics", parent=None):
if not HAS_QT:
return
super().__init__(parent)
self._stats: List[StatItem] = []
self._setup_ui(title)
def _setup_ui(self, title: str):
self.setStyleSheet("""
MetricsCard {
background-color: #2d2d2d;
border-radius: 8px;
padding: 15px;
}
QLabel {
color: #ffffff;
}
.metric-label {
color: #888888;
font-size: 12px;
}
.metric-value {
font-size: 18px;
font-weight: bold;
}
.metric-positive {
color: #4caf50;
}
.metric-negative {
color: #f44336;
}
""")
layout = QVBoxLayout(self)
layout.setContentsMargins(15, 15, 15, 15)
layout.setSpacing(15)
# Title
self.title_label = QLabel(title)
font = QFont()
font.setBold(True)
font.setPointSize(14)
self.title_label.setFont(font)
layout.addWidget(self.title_label)
# Stats grid
self.stats_layout = QGridLayout()
self.stats_layout.setSpacing(10)
layout.addLayout(self.stats_layout)
layout.addStretch()
def set_stats(self, stats: List[StatItem]):
"""Update displayed statistics."""
if not HAS_QT:
return
self._stats = stats
# Clear existing
while self.stats_layout.count():
item = self.stats_layout.takeAt(0)
if item.widget():
item.widget().deleteLater()
# Add stats
for i, stat in enumerate(stats):
row = i // 2
col = (i % 2) * 2
# Label
label = QLabel(stat.label)
label.setStyleSheet("color: #888888; font-size: 11px;")
self.stats_layout.addWidget(label, row * 2, col)
# Value with optional change
value_text = stat.value
if stat.change:
value_text += f" <span style='color: {'#4caf50' if stat.positive else '#f44336'}'>{stat.change}</span>"
value_label = QLabel(value_text)
value_label.setStyleSheet("font-size: 16px; font-weight: bold; color: #ffffff;")
self.stats_layout.addWidget(value_label, row * 2 + 1, col)
def update_stat(self, index: int, value: str, change: Optional[str] = None):
"""Update a single statistic."""
if 0 <= index < len(self._stats):
self._stats[index].value = value
self._stats[index].change = change
self.set_stats(self._stats)