Source code for districtheatingsim.gui.NetSimulationTab.producer_order_tab

"""Producer Order Tab Module
=========================

Tab for selecting and ordering heat producers in district heating networks.

:author: Dipl.-Ing. (FH) Jonas Pfeiffer
"""

import os

import geopandas as gpd

from PyQt6.QtWidgets import QVBoxLayout, QWidget, QGroupBox, QListWidget, QPushButton, \
    QMessageBox, QAbstractItemView, QListWidgetItem, QHBoxLayout, QLabel, QLineEdit

from PyQt6.QtCore import Qt

[docs] class ProducerOrderTab(QWidget): """ Widget for configuring heat producer selection and priority order. """
[docs] def __init__(self, dialog_config, parent=None): """ Initialize producer order tab. :param dialog_config: Configuration data. :type dialog_config: dict :param parent: Parent widget. :type parent: QWidget """ super().__init__(parent) self.parent = parent self.dialog_config = dialog_config self.initUI() self.percentage_inputs = []
[docs] def initUI(self): """ Initialize user interface components. """ layout = QVBoxLayout(self) producerGroup = QGroupBox("Erzeugerauswahl") producerGroup.setStyleSheet("QGroupBox { font-size: 11pt; font-weight: bold; }") producerLayout = QVBoxLayout() producerLayout.addLayout(self.create_producer_selection()) producerGroup.setLayout(producerLayout) layout.addWidget(producerGroup) self.load_producers()
[docs] def create_producer_selection(self): """ Create producer selection interface components. :return: Layout containing producer selection widgets. :rtype: QVBoxLayout """ layout = QVBoxLayout() self.producer_list_widget = QListWidget() self.producer_list_widget.setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection) layout.addWidget(self.producer_list_widget) self.add_producer_button = QPushButton("Erzeuger hinzufügen") self.add_producer_button.clicked.connect(self.add_producer_to_order) layout.addWidget(self.add_producer_button) self.remove_producer_button = QPushButton("Erzeuger entfernen") self.remove_producer_button.clicked.connect(self.remove_producer_from_order) layout.addWidget(self.remove_producer_button) self.producer_order_list_widget = QListWidget() self.producer_order_list_widget.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) layout.addWidget(self.producer_order_list_widget) self.producer_percentage_inputs = QVBoxLayout() layout.addLayout(self.producer_percentage_inputs) return layout
[docs] def load_producers(self): """ Load producers from unified GeoJSON file and populate list widget. """ filepath = self.parent.network_data_tab.networkInput.itemAt(1).widget().text() try: producers = self.read_producers_from_geojson(filepath) self.producer_list_widget.clear() for producer in producers: item = QListWidgetItem(producer['name']) item.setData(Qt.ItemDataRole.UserRole, producer) self.producer_list_widget.addItem(item) except FileNotFoundError as e: QMessageBox.warning(self, "Datei nicht gefunden", str(e))
[docs] def read_producers_from_geojson(self, filepath): """ Read producer data from unified GeoJSON file. :param filepath: Path to unified network GeoJSON file. :type filepath: str :return: List of producer dictionaries. :rtype: list :raises FileNotFoundError: If GeoJSON file not found. """ if not os.path.exists(filepath): raise FileNotFoundError(f"GeoJSON file not found: {filepath}") from districtheatingsim.net_generation.network_geojson_schema import NetworkGeoJSONSchema geojson_data = gpd.read_file(filepath) # Filter for generator features only generator_features = geojson_data[ geojson_data['feature_type'] == NetworkGeoJSONSchema.FEATURE_TYPE_GENERATOR ] producers = [] for idx, row in generator_features.iterrows(): producers.append({ 'name': f'Erzeugerstandort {idx + 1}', 'location': row['geometry'] }) return producers
[docs] def add_producer_to_order(self): """ Add selected producer to the order list. """ selected_items = self.producer_list_widget.selectedItems() for item in selected_items: producer = item.data(Qt.ItemDataRole.UserRole) # Check if the producer is already in the order list if not any(self.producer_order_list_widget.item(i).data(Qt.ItemDataRole.UserRole)['index'] == self.producer_list_widget.row(item) for i in range(self.producer_order_list_widget.count())): order_item = QListWidgetItem(producer['name']) order_item.setData(Qt.ItemDataRole.UserRole, {'name': producer['name'], 'index': self.producer_list_widget.row(item)}) self.producer_order_list_widget.addItem(order_item) self.update_producer_percentage_inputs()
[docs] def remove_producer_from_order(self): """ Remove selected producer from the order list. """ selected_items = self.producer_order_list_widget.selectedItems() for item in selected_items: self.producer_order_list_widget.takeItem(self.producer_order_list_widget.row(item)) self.update_producer_percentage_inputs()
[docs] def update_producer_percentage_inputs(self): """ Update percentage input fields for secondary producers. """ # Clear existing percentage inputs self.percentage_inputs.clear() while self.producer_percentage_inputs.count(): item = self.producer_percentage_inputs.takeAt(0) widget = item.widget() if widget: widget.deleteLater() # Add new percentage inputs for secondary producers count = self.producer_order_list_widget.count() if count > 1: for i in range(1, count): percentage_input_layout = QHBoxLayout() label = QLabel(f"Erzeuger {i+1} Prozentuale Erzeugung (%):") line_edit = QLineEdit() self.percentage_inputs.append(line_edit) percentage_input_layout.addWidget(label) percentage_input_layout.addWidget(line_edit) self.producer_percentage_inputs.addLayout(percentage_input_layout)