feat: инициализация проекта калькулятора питательных сред

This commit is contained in:
2026-05-05 12:25:30 +05:00
commit cde52d1123
10 changed files with 269674 additions and 0 deletions
+142
View File
@@ -0,0 +1,142 @@
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QTableWidgetItem, QComboBox
from model import Reagent
class Controller:
def __init__(self, view, model):
self.view = view
self.model = model
self.setup_connections()
def setup_connections(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.calculate)
self.view.save_btn.clicked.connect(self.save_composition)
self.view.load_btn.clicked.connect(self.load_composition)
# Авторасчёт при изменении количества среды
self.view.amount_input.valueChanged.connect(self.calculate)
# Авторасчёт при смене единицы измерения
self.view.amount_unit_combo.currentTextChanged.connect(self.calculate)
def add_reagent_row(self):
"""Добавляет новую строку в таблицу реагентов с предустановленными значениями"""
row = self.view.table.rowCount()
self.view.table.insertRow(row)
self.view.table.setItem(row, 0, QTableWidgetItem("Реагент"))
self.view.table.setItem(row, 1, QTableWidgetItem("1.0"))
unit_combo = QComboBox()
unit_combo.addItems(["нг", "мкг", "мг", "г", "кг", "нл", "мкл", "мл", "л"])
unit_combo.setCurrentText("мг")
self.view.table.setCellWidget(row, 2, unit_combo)
self.view.table.setItem(row, 3, QTableWidgetItem("1.0"))
self.view.table.setItem(row, 4, QTableWidgetItem(""))
def remove_reagent_row(self):
"""Удаляет выделенную строку из таблицы реагентов и из модели"""
current_row = self.view.table.currentRow()
if current_row >= 0:
self.view.table.removeRow(current_row)
if 0 <= current_row < len(self.model.reagents):
del self.model.reagents[current_row]
def calculate(self):
"""Выполняет расчёт количеств реагентов и растворителя"""
try:
self._update_model_from_view()
results = self.model.calculate_amounts()
self.view.update_results(results)
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(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)
if not all([name_item, percentage_item, conversion_item]):
continue
name = name_item.text()
percentage = float(percentage_item.text())
unit = unit_widget.currentText()
conversion_factor = float(conversion_item.text())
reagent = Reagent(name, percentage, unit, conversion_factor)
self.model.add_reagent(reagent)
def _update_view_from_model(self):
"""Обновляет интерфейс данными из модели"""
self.view.table.setRowCount(0)
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)
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(""))
def save_composition(self):
"""Сохраняет состав среды в JSON‑файл"""
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):
"""Загружает состав среды из JSON‑файла"""
filename, _ = QFileDialog.getOpenFileName(
self.view,
"Загрузить состав среды",
"",
"JSON Files (*.json);;All Files (*)"
)
if filename:
try:
self.model.load_from_file(filename)
self._update_view_from_model() # Исправлено: добавлены скобки ()
self.calculate()
QMessageBox.information(self.view, "Успех", "Состав среды успешно загружен!")
except Exception as e:
self.view.show_error(f"Ошибка загрузки: {str(e)}")