from PyQt5.QtWidgets import QFileDialog, QMessageBox, QTableWidgetItem, QComboBox from PyQt5.QtCore import Qt from PyQt5.QtGui import QColor import json from ..models.medium_model import MediumModel from ..models.reagent import Reagent from ..views.experiment_view import ExperimentDesignWindow class MediumController: def __init__(self, view): self.model = MediumModel() self.view = view self.doe_window = None self._connect_signals() self._setup_initial_data() def _connect_signals(self): self.view.add_row_btn.clicked.connect(self.add_reagent_row) self.view.remove_row_btn.clicked.connect(self.remove_reagent_row) self.view.calculate_btn.clicked.connect(self._perform_calculation) self.view.save_btn.clicked.connect(self.save_composition) self.view.load_btn.clicked.connect(self.load_composition) self.view.to_doe_btn.clicked.connect(self.send_to_doe) self.view.solvent_input.textChanged.connect(self.view.update_solvent_name) def _setup_initial_data(self): self.view.add_initial_rows() def add_reagent_row(self): self.view.add_new_row() def remove_reagent_row(self): self.view.remove_selected_row() def _perform_calculation(self): try: self._update_model_from_view() results, solvent_amount, solvent_percentage = self.model.calculate_amounts() self.view.update_results(results) self.view.update_solvent_result(solvent_amount, self.model.amount_unit) self.view.update_solvent_percent(solvent_percentage) except ValueError as e: self.view.show_error(f"Ошибка в данных: {str(e)}") except Exception as e: self.view.show_error(f"Неожиданная ошибка: {str(e)}") def _update_model_from_view(self): self.model.reagents.clear() self.model.total_amount = self.view.amount_input.value() self.model.amount_unit = self.view.amount_unit_combo.currentText() self.model.solvent = self.view.solvent_input.text() for row in range(1, self.view.table.rowCount()): name_item = self.view.table.item(row, 0) percentage_item = self.view.table.item(row, 1) unit_widget = self.view.table.cellWidget(row, 2) conversion_item = self.view.table.item(row, 3) dilution_item = self.view.table.item(row, 4) if not all([name_item, percentage_item, conversion_item]): continue try: name = name_item.text() percentage = float(percentage_item.text()) unit = unit_widget.currentText() if unit_widget else "мг" conversion_factor = float(conversion_item.text()) dilution_factor = float(dilution_item.text()) if dilution_item else 1.0 reagent = Reagent(name, percentage, unit, conversion_factor) reagent.dilution_factor = dilution_factor self.model.reagents.append(reagent) except ValueError as e: raise ValueError(f"Ошибка в строке {row + 1}: {str(e)}") def send_to_doe(self): """Передаёт данные о реагентах в окно планирования эксперимента""" reagents = self.view.get_reagents_data() if len(reagents) == 0: self.view.show_error("Нет реагентов для передачи в планировщик эксперимента!") return # Создаём или показываем существующее окно DoE if self.doe_window is None: self.doe_window = ExperimentDesignWindow() # Передаём данные в окно DoE self.doe_window.load_factors_from_reagents(reagents) self.doe_window.show() self.doe_window.raise_() self.doe_window.activateWindow() self.view.show_info(f"Передано {len(reagents)} реагентов в планировщик эксперимента\n" f"Каждый реагент добавлен как фактор.\n" f"Его концентрация (%) установлена как нулевой уровень.") def save_composition(self): filename, _ = QFileDialog.getSaveFileName(self.view, "Сохранить состав среды", "", "JSON Files (*.json);;All Files (*)") if filename: if not filename.lower().endswith('.json'): filename += '.json' try: self._update_model_from_view() self.model.save_to_file(filename) QMessageBox.information(self.view, "Успех", "Состав среды успешно сохранён!") except Exception as e: self.view.show_error(f"Ошибка сохранения: {str(e)}") def load_composition(self): filename, _ = QFileDialog.getOpenFileName(self.view, "Загрузить состав среды", "", "JSON Files (*.json);;All Files (*)") if filename: try: self.model.load_from_file(filename) self._update_view_from_model() QMessageBox.information(self.view, "Успех", "Состав среды успешно загружен") except FileNotFoundError: QMessageBox.critical(self.view, "Ошибка", f"Файл не найден: {filename}") except json.JSONDecodeError as e: QMessageBox.critical(self.view, "Ошибка", f"Неверный формат JSON-файла: {str(e)}") except Exception as e: QMessageBox.critical(self.view, "Ошибка", f"Ошибка при загрузке состава: {str(e)}") def _update_view_from_model(self): while self.view.table.rowCount() > 1: self.view.table.removeRow(1) if self.view.table.rowCount() == 0: self.view.add_solvent_row() self.view.amount_input.setValue(self.model.total_amount) index = self.view.amount_unit_combo.findText(self.model.amount_unit) if index >= 0: self.view.amount_unit_combo.setCurrentIndex(index) self.view.solvent_input.setText(self.model.solvent) self.view.update_solvent_name() for reagent in self.model.reagents: row = self.view.table.rowCount() self.view.table.insertRow(row) self.view.table.setItem(row, 0, QTableWidgetItem(reagent.name)) self.view.table.setItem(row, 1, QTableWidgetItem(f"{reagent.percentage:.2f}")) unit_combo = QComboBox() unit_combo.addItems(["нг", "мкг", "мг", "г", "кг", "нл", "мкл", "мл", "л"]) unit_combo.setCurrentText(reagent.unit) self.view.table.setCellWidget(row, 2, unit_combo) self.view.table.setItem(row, 3, QTableWidgetItem(f"{reagent.conversion_factor:.2f}")) self.view.table.setItem(row, 4, QTableWidgetItem(f"{getattr(reagent, 'dilution_factor', 1.0):.3f}")) self.view.table.setItem(row, 5, QTableWidgetItem("")) self.view.clear_results()