EU-Utility/premium/widgets/dashboard_widget.py

195 lines
5.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Base widget components for the dashboard.
"""
from typing import Any, Optional, Callable
try:
from PyQt6.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton,
QFrame, QSizePolicy
)
from PyQt6.QtCore import Qt, pyqtSignal
from PyQt6.QtGui import QFont
HAS_QT = True
except ImportError:
HAS_QT = False
QWidget = object
pyqtSignal = lambda *a, **k: None
class WidgetHeader(QFrame if HAS_QT else object):
"""Header component for widgets with title and controls."""
collapsed_changed = pyqtSignal(bool) if HAS_QT else None
close_requested = pyqtSignal() if HAS_QT else None
def __init__(self, title: str = "Widget", icon: str = "📦", parent=None):
if not HAS_QT:
return
super().__init__(parent)
self._collapsed = False
self._setup_ui(title, icon)
def _setup_ui(self, title: str, icon: str):
self.setFrameShape(QFrame.Shape.StyledPanel)
self.setStyleSheet("""
WidgetHeader {
background-color: #2d2d2d;
border-radius: 8px 8px 0 0;
padding: 8px;
}
""")
layout = QHBoxLayout(self)
layout.setContentsMargins(10, 5, 10, 5)
layout.setSpacing(10)
# Icon
self.icon_label = QLabel(icon)
self.icon_label.setStyleSheet("font-size: 16px;")
layout.addWidget(self.icon_label)
# Title
self.title_label = QLabel(title)
font = QFont()
font.setBold(True)
self.title_label.setFont(font)
self.title_label.setStyleSheet("color: #ffffff;")
layout.addWidget(self.title_label)
layout.addStretch()
# Collapse button
self.collapse_btn = QPushButton("")
self.collapse_btn.setFixedSize(24, 24)
self.collapse_btn.setStyleSheet("""
QPushButton {
background-color: #3d3d3d;
color: #ffffff;
border: none;
border-radius: 4px;
}
QPushButton:hover {
background-color: #4d4d4d;
}
""")
self.collapse_btn.clicked.connect(self._toggle_collapse)
layout.addWidget(self.collapse_btn)
# Close button
self.close_btn = QPushButton("×")
self.close_btn.setFixedSize(24, 24)
self.close_btn.setStyleSheet("""
QPushButton {
background-color: #3d3d3d;
color: #ff6b6b;
border: none;
border-radius: 4px;
font-size: 16px;
font-weight: bold;
}
QPushButton:hover {
background-color: #ff6b6b;
color: #ffffff;
}
""")
self.close_btn.clicked.connect(lambda: self.close_requested.emit())
layout.addWidget(self.close_btn)
def _toggle_collapse(self):
self._collapsed = not self._collapsed
self.collapse_btn.setText("" if self._collapsed else "")
self.collapsed_changed.emit(self._collapsed)
def set_collapsed(self, collapsed: bool):
self._collapsed = collapsed
self.collapse_btn.setText("" if collapsed else "")
class WidgetContent(QFrame if HAS_QT else object):
"""Content container for widgets."""
def __init__(self, parent=None):
if not HAS_QT:
return
super().__init__(parent)
self.setFrameShape(QFrame.Shape.StyledPanel)
self.setStyleSheet("""
WidgetContent {
background-color: #1e1e1e;
border-radius: 0 0 8px 8px;
padding: 10px;
}
""")
self._layout = QVBoxLayout(self)
self._layout.setContentsMargins(10, 10, 10, 10)
self._layout.setSpacing(10)
def add_widget(self, widget):
if HAS_QT:
self._layout.addWidget(widget)
def layout(self):
return self._layout if HAS_QT else None
class DashboardWidget(QFrame if HAS_QT else object):
"""Complete dashboard widget with header and content."""
def __init__(
self,
title: str = "Widget",
icon: str = "📦",
size: tuple = (300, 200),
parent=None
):
if not HAS_QT:
return
super().__init__(parent)
self._size = size
self._setup_ui(title, icon)
def _setup_ui(self, title: str, icon: str):
self.setStyleSheet("""
DashboardWidget {
background-color: transparent;
border: 1px solid #3d3d3d;
border-radius: 8px;
}
""")
layout = QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
# Header
self.header = WidgetHeader(title, icon, self)
self.header.collapsed_changed.connect(self._on_collapse_changed)
layout.addWidget(self.header)
# Content
self.content = WidgetContent(self)
layout.addWidget(self.content)
self.setFixedSize(*self._size)
def _on_collapse_changed(self, collapsed: bool):
self.content.setVisible(not collapsed)
if collapsed:
self.setFixedHeight(self.header.height())
else:
self.setFixedHeight(self._size[1])
def set_content_widget(self, widget: QWidget):
"""Set the main content widget."""
if HAS_QT:
# Clear existing
while self.content.layout().count():
item = self.content.layout().takeAt(0)
if item.widget():
item.widget().deleteLater()
self.content.layout().addWidget(widget)