"""
Energy System Tab Utilities Module
===================================
:author: Dipl.-Ing. (FH) Jonas Pfeiffer
Utility classes for Energy System Tab, including collapsible sections, checkable combo boxes, and custom JSON encoding.
"""
from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QPushButton, QSizePolicy, QComboBox)
from PyQt6.QtCore import QSize, Qt
import json
import numpy as np
import pandas as pd
from districtheatingsim.heat_generators import *
[docs]
class CheckableComboBox(QComboBox):
"""
Combo box that allows multiple items to be checked.
"""
[docs]
def __init__(self, parent=None):
"""
Initialize the CheckableComboBox.
:param parent: Parent widget.
:type parent: QWidget
"""
super(CheckableComboBox, self).__init__(parent)
self.view().pressed.connect(self.handleItemPressed)
self.setModelColumn(0)
self.checked_items = []
[docs]
def handleItemPressed(self, index):
"""
Handle item pressed event to toggle check state.
:param index: Index of the pressed item.
:type index: QModelIndex
"""
item = self.model().itemFromIndex(index)
if item.checkState() == Qt.CheckState.Checked:
item.setCheckState(Qt.CheckState.Unchecked)
self.checked_items.remove(item.text())
else:
item.setCheckState(Qt.CheckState.Checked)
self.checked_items.append(item.text())
self.updateText()
[docs]
def updateText(self):
"""
Update displayed text to show checked items.
"""
if self.checked_items:
self.setEditText(', '.join(self.checked_items))
else:
self.setEditText('')
[docs]
def addItem(self, text, data=None):
"""
Add item to combo box.
:param text: Item text.
:type text: str
:param data: Associated data.
:type data: Any
"""
super(CheckableComboBox, self).addItem(text, data)
item = self.model().item(self.count() - 1)
item.setCheckState(Qt.CheckState.Unchecked)
[docs]
def addItems(self, texts):
"""
Add multiple items to combo box.
:param texts: List of item texts to add.
:type texts: list
"""
for text in texts:
self.addItem(text)
[docs]
def setItemChecked(self, text, checked=True):
"""
Set check state of an item.
:param text: Item text.
:type text: str
:param checked: Check state.
:type checked: bool
"""
index = self.findText(text)
if index != -1:
item = self.model().item(index)
item.setCheckState(Qt.CheckState.Checked if checked else Qt.CheckState.Unchecked)
if checked:
if text not in self.checked_items:
self.checked_items.append(text)
else:
if text in self.checked_items:
self.checked_items.remove(text)
self.updateText()
[docs]
def clear(self):
"""
Clear all items from combo box.
"""
super(CheckableComboBox, self).clear()
self.checked_items = []
[docs]
def checkedItems(self):
"""
Get list of checked items.
:return: List of checked items.
:rtype: list
"""
return self.checked_items
[docs]
class CustomJSONEncoder(json.JSONEncoder):
"""
Custom JSON Encoder for handling numpy arrays, pandas DataFrames, and custom objects.
"""
[docs]
def default(self, obj):
try:
if isinstance(obj, np.ndarray):
return obj.tolist()
if isinstance(obj, np.integer):
return int(obj)
if isinstance(obj, np.floating):
return float(obj)
if isinstance(obj, pd.DataFrame):
# Use 'split' format for DataFrame serialization
return obj.to_dict(orient='split')
if isinstance(obj, (BaseHeatGenerator, BaseStrategy, STES)):
return obj.to_dict()
return super().default(obj)
except TypeError as e:
print(f"Failed to encode {obj} of type {type(obj)}")
raise e