""" Главное окно приложения - содержит меню, панели и canvas """ from PySide6.QtWidgets import ( QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QSplitter, QMenuBar, QMenu, QStatusBar, QMessageBox, QFileDialog, QToolBar, QFrame, QScrollArea, QLabel ) from PySide6.QtCore import Qt, QSize from PySide6.QtGui import QAction, QKeySequence from views.layer_widget import LayerWidget from views.canvas_widget import SolarCanvas from views.control_panel import ControlPanel from views.timelapse_dialog import TimelapseDialog from views.metadata_viewer import MetadataViewer class MainWindow(QMainWindow): """Главное окно приложения""" def __init__(self, controller): super().__init__() self.controller = controller self.init_ui() def init_ui(self): """Инициализация пользовательского интерфейса""" self.setWindowTitle("Helioviewer Solar Viewer - Профессиональный просмотрщик снимков Солнца") self.setMinimumSize(1200, 800) # Центральный виджет central_widget = QWidget() self.setCentralWidget(central_widget) # Основной layout main_layout = QHBoxLayout(central_widget) main_layout.setContentsMargins(0, 0, 0, 0) # Создаем сплиттер для левой панели и canvas splitter = QSplitter(Qt.Orientation.Horizontal) main_layout.addWidget(splitter) # Левая панель (с прокруткой) left_panel = self.create_left_panel_with_scroll() splitter.addWidget(left_panel) # Устанавливаем начальную ширину сплиттера splitter.setSizes([400, self.width() - 400]) # Правая область (canvas) right_area = self.create_right_area() splitter.addWidget(right_area) # Создаем меню self.create_menu_bar() # Создаем статус бар self.status_bar = QStatusBar() self.setStatusBar(self.status_bar) self.status_bar.showMessage("Готов к работе") # Добавляем тулбар для быстрого доступа self.create_toolbar() def create_left_panel_with_scroll(self) -> QWidget: """ Создает левую панель с прокруткой, где все виджеты равномерно распределяют пространство """ # Внешний контейнер для скролла scroll_container = QWidget() scroll_layout = QVBoxLayout(scroll_container) scroll_layout.setContentsMargins(0, 0, 0, 0) # Создаем QScrollArea scroll_area = QScrollArea() scroll_area.setWidgetResizable(True) # Позволяет виджету изменять размер scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) scroll_area.setStyleSheet(""" QScrollArea { border: none; background-color: #2b2b2b; } QScrollBar:vertical { background-color: #2b2b2b; width: 12px; border-radius: 6px; } QScrollBar::handle:vertical { background-color: #555; border-radius: 6px; min-height: 20px; } QScrollBar::handle:vertical:hover { background-color: #777; } QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { height: 0px; } """) # Внутренний контейнер для всех виджетов content_widget = QWidget() content_widget.setStyleSheet("background-color: #2b2b2b;") layout = QVBoxLayout(content_widget) layout.setSpacing(10) layout.setContentsMargins(10, 10, 10, 10) # Панель управления (выбор даты, спектра) self.control_panel = ControlPanel(self.controller) layout.addWidget(self.control_panel, 1) # stretch factor = 1 # Разделитель layout.addWidget(self.create_separator()) # Заголовок слоев title_layers = self.create_section_title("📁 Слои изображений") layout.addWidget(title_layers) # Виджет слоев - будет занимать столько места, сколько нужно self.layer_widget = LayerWidget(self.controller) layout.addWidget(self.layer_widget, 2) # stretch factor = 2 (больше места) # Разделитель layout.addWidget(self.create_separator()) # Заголовок метаданных title_metadata = self.create_section_title("📊 Метаданные FITS") layout.addWidget(title_metadata) # Просмотрщик метаданных self.metadata_viewer = MetadataViewer() layout.addWidget(self.metadata_viewer, 1) # stretch factor = 1 # Растягивающийся спейсер внизу (опционально) layout.addStretch() # Устанавливаем content_widget в scroll_area scroll_area.setWidget(content_widget) # Добавляем scroll_area в контейнер scroll_layout.addWidget(scroll_area) return scroll_container def create_separator(self) -> QFrame: """Создает линию-разделитель""" separator = QFrame() separator.setFrameShape(QFrame.Shape.HLine) separator.setFrameShadow(QFrame.Shadow.Sunken) separator.setStyleSheet("background-color: #555; max-height: 1px;") return separator def create_section_title(self, title: str) -> QLabel: """Создает заголовок секции""" label = QLabel(title) label.setStyleSheet(""" font-weight: bold; font-size: 14px; padding: 8px 5px; background-color: #3c3c3c; border-radius: 4px; margin-top: 5px; margin-bottom: 5px; """) label.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter) return label def create_right_area(self) -> QWidget: """Создает правую область с canvas""" area = QWidget() layout = QVBoxLayout(area) layout.setContentsMargins(0, 0, 0, 0) # Canvas для отображения изображений self.canvas = SolarCanvas(self.controller) layout.addWidget(self.canvas) return area def create_menu_bar(self): """Создает меню приложения""" menubar = self.menuBar() # Меню Файл file_menu = menubar.addMenu("📁 Файл") # Действия для меню Файл self.setup_action = QAction("⚙️ Настройки", self) self.exit_action = QAction("🚪 Выход", self) self.exit_action.setShortcut(QKeySequence.StandardKey.Quit) self.exit_action.triggered.connect(self.close) file_menu.addAction(self.setup_action) file_menu.addSeparator() file_menu.addAction(self.exit_action) # Меню Инструменты tools_menu = menubar.addMenu("🛠️ Инструменты") self.timelapse_action = QAction("🎬 Таймлапс...", self) self.timelapse_action.triggered.connect(self.open_timelapse_dialog) tools_menu.addAction(self.timelapse_action) # Меню Справка help_menu = menubar.addMenu("❓ Справка") about_action = QAction("ℹ️ О программе", self) about_action.triggered.connect(self.show_about) help_menu.addAction(about_action) def create_toolbar(self): """Создает панель инструментов""" toolbar = QToolBar("Быстрый доступ") self.addToolBar(toolbar) toolbar.setIconSize(QSize(24, 24)) def open_timelapse_dialog(self): """Открывает диалог создания таймлапса""" dialog = TimelapseDialog(self.controller, self) dialog.exec() def show_about(self): """Показывает информацию о программе""" QMessageBox.about( self, "О программе", "Helioviewer Solar Viewer v1.0\n\n" "Профессиональный просмотрщик снимков Солнца\n" "Использует данные Helioviewer API\n\n" "Возможности:\n" "• Загрузка снимков в различных спектрах\n" "• Многослойный режим с наложением\n" "• Создание таймлапс-анимаций\n" "• Просмотр FITS-метаданных\n\n" "© 2024 SolarViewer Team" ) def update_status(self, message: str, timeout: int = 3000): """Обновляет статус в статус-баре""" self.status_bar.showMessage(message, timeout) def update_layer_list(self, layers): """Обновляет список слоев""" self.layer_widget.update_layers(layers) def get_control_panel(self): """Возвращает панель управления""" return self.control_panel