/
O.S.Prog
/
InstrumentProtocol
Обзор
Документация
Войти
/
O.S.Prog
/
InstrumentProtocol
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
ui/main_window.py
282 строки
12 KB
O.S.Prog
Initial commit: InstrumentProtocol v2.0
17 июл 2026, 15:11
17 июл 2026, 15:11
1e845bd
Код
Авторство
О чём код?
from PyQt6.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QComboBox, QMessageBox, QInputDialog, QFrame) from PyQt6.QtCore import Qt, pyqtSignal from core.settings_manager import SettingsManager PROTOCOL_NAMES = { "Рентген": "рентгенологического", "УЗИ": "ультразвукового", "ФГС": "фиброгастродуоденоскопического", "ЭКГ": "электрокардиографического", "МРТ": "магнитно-резонансного", "МСКТ/КТ": "компьютерно-томографического", "Спирография": "спирографического", } class MainWindow(QMainWindow): research_selected = pyqtSignal(str) def __init__(self, login="", full_name="", encryption_key=None): super().__init__() self.login = login self.full_name = full_name self.encryption_key = encryption_key self.settings = SettingsManager() self.setWindowTitle("Протокол инструментального исследования") self.setGeometry(100, 100, 500, 350) self.setFixedSize(600, 500) self.default_types = [ "Рентген", "УЗИ", "ФГС", "ЭКГ", "МРТ", "МСКТ/КТ", "Спирография" ] central_widget = QWidget() self.setCentralWidget(central_widget) layout = QVBoxLayout() layout.setSpacing(15) # Заголовок title = QLabel("ПРОТОКОЛ ИНСТРУМЕНТАЛЬНОГО\nИССЛЕДОВАНИЯ") title.setStyleSheet("font-size: 18px; font-weight: bold; padding: 10px;") title.setAlignment(Qt.AlignmentFlag.AlignCenter) layout.addWidget(title) # Инфо-панель self.info_frame = QFrame() self.info_frame.setStyleSheet("background-color: #ecf0f1; border-radius: 5px; padding: 10px;") info_layout = QVBoxLayout() self.hospital_label = QLabel() self.doctor_label = QLabel(f"👨⚕️ Врач: <b>{self.full_name}</b>") info_layout.addWidget(self.hospital_label) info_layout.addWidget(self.doctor_label) self.info_frame.setLayout(info_layout) layout.addWidget(self.info_frame) # Выбор типа исследования type_layout = QHBoxLayout() type_layout.addWidget(QLabel("Тип исследования:")) self.type_combo = QComboBox() self.type_combo.setStyleSheet("font-size: 14px; padding: 5px;") self.type_combo.setMinimumWidth(200) self.load_types() type_layout.addWidget(self.type_combo) type_layout.addStretch() layout.addLayout(type_layout) # Кнопка Начать start_btn = QPushButton("▶ НАЧАТЬ") start_btn.setStyleSheet(""" QPushButton { font-size: 16px; font-weight: bold; padding: 12px; background-color: #27ae60; color: white; border: none; border-radius: 5px; } QPushButton:hover { background-color: #219a52; } """) start_btn.clicked.connect(self.start_research) layout.addWidget(start_btn) # Добавить/удалить тип manage_layout = QHBoxLayout() add_btn = QPushButton("+ Добавить тип") add_btn.setStyleSheet(self._btn_style("#3498db", "#2980b9")) add_btn.clicked.connect(self.add_type) manage_layout.addWidget(add_btn) del_btn = QPushButton("- Удалить тип") del_btn.setStyleSheet(self._btn_style("#e74c3c", "#c0392b")) del_btn.clicked.connect(self.delete_type) manage_layout.addWidget(del_btn) layout.addLayout(manage_layout) layout.addStretch() # Нижние кнопки bottom_layout = QHBoxLayout() archive_btn = QPushButton("📂 Архив") archive_btn.setStyleSheet(self._btn_style("#3498db", "#2980b9")) archive_btn.clicked.connect(self.open_archive) bottom_layout.addWidget(archive_btn) settings_btn = QPushButton("⚙️ Настройки") settings_btn.setStyleSheet(self._btn_style("#3498db", "#2980b9")) settings_btn.clicked.connect(self.open_settings) bottom_layout.addWidget(settings_btn) patient_search_btn = QPushButton("🔍 Поиск по пациенту") patient_search_btn.setStyleSheet(self._btn_style("#3498db", "#2980b9")) patient_search_btn.clicked.connect(self.open_patient_search) bottom_layout.addWidget(patient_search_btn) exit_btn = QPushButton("🚪 Выход") exit_btn.setStyleSheet(self._btn_style("#95a5a6", "#7f8c8d")) exit_btn.clicked.connect(self.close) bottom_layout.addWidget(exit_btn) layout.addLayout(bottom_layout) central_widget.setLayout(layout) self.update_info_panel() def _btn_style(self, bg, hover): return f""" QPushButton {{ font-size: 14px; font-weight: bold; padding: 10px; background-color: {bg}; color: white; border: none; border-radius: 5px; }} QPushButton:hover {{ background-color: {hover}; }} """ def _get_custom_types_key(self): return f"custom_research_types_{self.login}" def load_types(self): self.type_combo.clear() for t in self.default_types: self.type_combo.addItem(t) custom = self.settings.get(self._get_custom_types_key(), []) for t in custom: self.type_combo.addItem(t) def add_type(self): name, ok = QInputDialog.getText(self, "Новый тип исследования", "Введите название типа\n(например: Денситометрия):") if not ok or not name.strip(): return name = name.strip() # Для пользовательского типа спрашиваем прилагательное adj, ok = QInputDialog.getText( self, "Название в протоколе", f"Протокол ____________ исследования\n\nВведите прилагательное\n(например: денситометрического):" ) if not ok or not adj.strip(): return adj = adj.strip() custom = self.settings.get(self._get_custom_types_key(), []) if name not in self.default_types and name not in custom: custom.append(name) self.settings.set(self._get_custom_types_key(), custom) # Сохраняем прилагательное adj_dict = self.settings.get("protocol_adjectives", {}) adj_dict[name] = adj self.settings.set("protocol_adjectives", adj_dict) self.settings.save_settings() self.load_types() self.type_combo.setCurrentText(name) QMessageBox.information(self, "Готово", f"Тип '{name}' добавлен.") def delete_type(self): name = self.type_combo.currentText() if not name: return if name in self.default_types: QMessageBox.warning(self, "Ошибка", "Стандартные типы нельзя удалить.") return reply = QMessageBox.question( self, "Удалить тип", f"Удалить тип '{name}'?", QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No ) if reply == QMessageBox.StandardButton.Yes: custom = self.settings.get(self._get_custom_types_key(), []) if name in custom: custom.remove(name) self.settings.set(self._get_custom_types_key(), custom) self.settings.save_settings() self.load_types() def start_research(self): research_type = self.type_combo.currentText() if research_type: self.research_selected.emit(research_type) def open_archive(self): from ui.archive_window import ArchiveWindow self.archive_window = ArchiveWindow( parent=self, research_type=self.type_combo.currentText(), readonly=False, full_name=self.full_name, encryption_key=self.encryption_key ) self.archive_window.protocol_selected.connect(self._on_archive_protocol_selected) self.archive_window.show() self.archive_window.raise_() self.archive_window.activateWindow() def _on_archive_protocol_selected(self, filepath, fio, birth_date, hospital, research_type, description, conclusion, exam_date, exam_time, doctor_name, readonly): from ui.editor_window import EditorWindow if readonly: # Чужой протокол — открываем в отдельном окне, не скрывая главное self.viewer = EditorWindow(research_type, "", "", readonly=True, encryption_key=self.encryption_key) self.viewer.current_filepath = filepath self.viewer.hospital_name.setText(hospital) self.viewer.patient_widget.set_fio(fio) self.viewer.patient_widget.set_birth_date(birth_date) self.viewer.exam_date.setText(exam_date) self.viewer.exam_time.setText(exam_time) self.viewer.description_editor.setPlainText(description) self.viewer.conclusion_editor.setPlainText(conclusion) self.viewer.setWindowTitle(f"[ТОЛЬКО ПРОСМОТР] Протокол {research_type.lower()} исследования - Редактор") self.viewer.show() else: # Свой протокол — открываем в редакторе self.hide() self.editor_window = EditorWindow(research_type, self.login, self.full_name, readonly=False, encryption_key=self.encryption_key) self.editor_window.current_filepath = filepath self.editor_window.hospital_name.setText(hospital) self.editor_window.patient_widget.set_fio(fio) self.editor_window.patient_widget.set_birth_date(birth_date) self.editor_window.exam_date.setText(exam_date) self.editor_window.exam_time.setText(exam_time) self.editor_window.description_editor.setPlainText(description) self.editor_window.conclusion_editor.setPlainText(conclusion) self.editor_window.show() def open_settings(self): from ui.settings_window import SettingsWindow self.hide() settings_dialog = SettingsWindow(login=self.login) settings_dialog.exec() self.settings.load_settings() self.show() self.update_info_panel() def update_info_panel(self): hospital = self.settings.get_last_hospital() self.hospital_label.setText(f"🏥 Лечебное учреждение: <b>{hospital if hospital else 'не выбрано'}</b>") def open_patient_search(self): from ui.patient_search_window import PatientSearchWindow self.patient_search = PatientSearchWindow( parent=self, full_name=self.full_name, encryption_key=self.encryption_key ) self.patient_search.protocol_selected.connect(self._on_archive_protocol_selected) self.patient_search.show()