HelioParser/views/main_window.py
2026-06-10 17:33:12 +03:00

251 lines
No EOL
9.7 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Главное окно приложения - содержит меню, панели и 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