460 lines
17 KiB
Python
460 lines
17 KiB
Python
from datetime import datetime as dt
|
||
|
||
from PyQt5.QtWidgets import (
|
||
QWidget, QPushButton, QMenuBar, QHBoxLayout, QVBoxLayout, QLabel,
|
||
QDockWidget, QTabWidget, QProgressBar, QAction, QMainWindow, QGridLayout
|
||
)
|
||
from PyQt5.QtGui import QIcon
|
||
from PyQt5.QtCore import Qt
|
||
from PyQt5.QtWidgets import QSizePolicy as QSP
|
||
|
||
from gui.settings_window import SystemSettings, OperatorSettings, FilterSettings
|
||
from gui.report_gui import ReportSettings
|
||
from base.base import PlotItems
|
||
|
||
|
||
class StartWidget(QWidget):
|
||
"""
|
||
Виджет выбора режима работы приложения.
|
||
|
||
Содержит кнопки для перехода в различные режимы:
|
||
- Сканирование папки в реальном времени
|
||
- Редактор отчётов
|
||
- Обработка клиентских трейсов
|
||
"""
|
||
|
||
def __init__(self) -> None:
|
||
super().__init__()
|
||
self._build_main_layout()
|
||
|
||
def get_widget(self) -> QWidget:
|
||
"""
|
||
Возвращает текущий виджет.
|
||
"""
|
||
return self
|
||
|
||
def _build_main_layout(self) -> None:
|
||
"""
|
||
Строит макет виджета с заголовком и кнопками выбора режима.
|
||
"""
|
||
self.resize(800, 800)
|
||
|
||
# Создаем кнопки для различных режимов работы
|
||
self.btn_scanning = QPushButton("Real time folder scanning")
|
||
self.btn_scanning.setFixedWidth(350)
|
||
self.btn_report = QPushButton("Raport editor")
|
||
self.btn_report.setFixedWidth(350)
|
||
self.btn_client = QPushButton("Client trace processor")
|
||
self.btn_client.setFixedWidth(350)
|
||
|
||
# Размещение кнопок в горизонтальном макете
|
||
button_layout = QHBoxLayout()
|
||
button_layout.setSpacing(2)
|
||
button_layout.addWidget(self.btn_scanning)
|
||
button_layout.addWidget(self.btn_report)
|
||
button_layout.addWidget(self.btn_client)
|
||
button_container = QWidget()
|
||
button_container.setLayout(button_layout)
|
||
|
||
# Создаем основной вертикальный макет с заголовком и кнопками
|
||
main_layout = QVBoxLayout()
|
||
title_label = QLabel("Select work mode")
|
||
title_label.setStyleSheet(
|
||
"""QLabel{
|
||
color: #ffffff;
|
||
font-size: 40px;
|
||
font-weight: bold;
|
||
font-family: "Segoe UI", sans-serif;
|
||
}"""
|
||
)
|
||
main_layout.addWidget(title_label, alignment=Qt.AlignCenter)
|
||
main_layout.addWidget(button_container)
|
||
self.setLayout(main_layout)
|
||
|
||
|
||
class CustomStatusBar(QWidget):
|
||
"""
|
||
Кастомный виджет для статус-бара, отображающий режим, заметку и прогресс.
|
||
"""
|
||
|
||
def __init__(self) -> None:
|
||
super().__init__()
|
||
self._build_status_bar()
|
||
|
||
def get_widget(self) -> QWidget:
|
||
"""
|
||
Возвращает виджет статус-бара.
|
||
"""
|
||
return self
|
||
|
||
def set_mode(self, msg: str = '') -> None:
|
||
"""
|
||
Устанавливает текст режима в статус-баре.
|
||
|
||
:param msg: Сообщение для отображения.
|
||
"""
|
||
if not isinstance(msg, str):
|
||
msg = str(msg)
|
||
self._mode_label.setText(msg)
|
||
self._mode_label.adjustSize()
|
||
|
||
def set_note(self, msg: str = '') -> None:
|
||
"""
|
||
Устанавливает текст заметки в статус-баре.
|
||
|
||
:param msg: Сообщение для отображения.
|
||
"""
|
||
if not isinstance(msg, str):
|
||
msg = str(msg)
|
||
self._note_label.setText(msg)
|
||
self._note_label.adjustSize()
|
||
|
||
def set_progress(self, percent: int = 0) -> None:
|
||
"""
|
||
Устанавливает значение прогресс-бара.
|
||
|
||
:param percent: Значение прогресса (от 0 до 100).
|
||
"""
|
||
if not isinstance(percent, int):
|
||
percent = 0
|
||
elif percent < 0:
|
||
percent = 0
|
||
elif percent > 100:
|
||
percent = 100
|
||
self._progress_bar.setValue(percent)
|
||
|
||
def _build_status_bar(self) -> None:
|
||
"""
|
||
Создает и настраивает компоненты статус-бара.
|
||
"""
|
||
# Создаем горизонтальный макет с отступами и промежутками
|
||
layout = QHBoxLayout()
|
||
layout.setContentsMargins(10, 1, 10, 1)
|
||
layout.setSpacing(15)
|
||
|
||
# Инициализируем компоненты статус-бара
|
||
self._mode_label = QLabel()
|
||
self._note_label = QLabel()
|
||
self._progress_bar = QProgressBar()
|
||
self._progress_bar.setRange(0, 100)
|
||
self._progress_bar.setValue(0)
|
||
self._progress_bar.setMinimumWidth(250)
|
||
self._progress_bar.setMaximumHeight(10)
|
||
self._progress_bar.setTextVisible(False)
|
||
|
||
# Устанавливаем политику размеров для компонентов
|
||
self._mode_label.setSizePolicy(QSP.Policy.Preferred, QSP.Policy.Preferred)
|
||
self._note_label.setSizePolicy(QSP.Policy.MinimumExpanding, QSP.Policy.Preferred)
|
||
self._progress_bar.setSizePolicy(QSP.Policy.Fixed, QSP.Policy.Preferred)
|
||
|
||
# Добавляем компоненты в макет
|
||
layout.addWidget(self._progress_bar)
|
||
layout.addWidget(self._note_label)
|
||
layout.addStretch(1)
|
||
layout.addWidget(self._mode_label)
|
||
|
||
self.setLayout(layout)
|
||
self.setSizePolicy(QSP.Policy.Expanding, QSP.Policy.Preferred)
|
||
|
||
|
||
class CustomTabWidget(QTabWidget):
|
||
"""
|
||
Кастомный виджет-вкладка.
|
||
|
||
Позволяет создавать вкладки с виджетом графика и закрывать их.
|
||
"""
|
||
|
||
def __init__(self):
|
||
super().__init__()
|
||
self._build_tab_widget()
|
||
|
||
def get_widget(self) -> QWidget:
|
||
"""
|
||
Возвращает виджет.
|
||
"""
|
||
return self
|
||
|
||
def _build_tab_widget(self) -> None:
|
||
"""
|
||
Настраивает виджет вкладок: включает возможность закрытия вкладок.
|
||
"""
|
||
self.setTabsClosable(True)
|
||
self.tabCloseRequested.connect(self.close_tab)
|
||
|
||
def create_tab(self, plot_widget: QWidget) -> None:
|
||
"""
|
||
Создает новую вкладку с виджетом графика.
|
||
|
||
Извлекает из виджета необходимые данные, сохраняет их в свойствах вкладки.
|
||
|
||
:param plot_widget: Виджет, содержащий график.
|
||
"""
|
||
# Извлекаем объект PlotItems, сохранённый в свойстве виджета
|
||
plot_items: PlotItems = plot_widget.property("pyqt_container")
|
||
new_tab = QWidget()
|
||
new_tab.setProperty("reg_items", plot_items.regions)
|
||
new_tab.setProperty("curve_items", plot_items.curves)
|
||
new_tab.setProperty("qt_items", plot_items.qt_items)
|
||
grid_layout = QGridLayout()
|
||
grid_layout.addWidget(plot_widget)
|
||
new_tab.setLayout(grid_layout)
|
||
tab_label = "SF_trace_" + dt.now().strftime('%Y_%m_%d-%H_%M_%S')
|
||
self.addTab(new_tab, tab_label)
|
||
self.setCurrentWidget(new_tab)
|
||
|
||
def close_tab(self, index: int) -> None:
|
||
"""
|
||
Закрывает вкладку по заданному индексу.
|
||
|
||
:param index: Индекс вкладки для закрытия.
|
||
"""
|
||
if self.count() > index and index >= 0:
|
||
self.removeTab(index)
|
||
|
||
|
||
class CustomMenuBar(QMenuBar):
|
||
"""
|
||
Кастомное главное меню с док-виджетами для различных настроек.
|
||
"""
|
||
|
||
def __init__(self,
|
||
operator_settings: OperatorSettings,
|
||
system_settings: SystemSettings,
|
||
report_settings: ReportSettings,
|
||
filter_settings: FilterSettings) -> None:
|
||
super().__init__()
|
||
self._operator_settings = operator_settings
|
||
self._system_settings = system_settings
|
||
self._report_settings = report_settings
|
||
self._filter_settings = filter_settings
|
||
self._build_dock_widgets()
|
||
self._build_menu()
|
||
|
||
def get_widget(self) -> QWidget:
|
||
"""
|
||
Возвращает виджет меню.
|
||
"""
|
||
return self
|
||
|
||
def setup(self, parent: QMainWindow) -> None:
|
||
"""
|
||
Добавляет док-виджеты и устанавливает главное меню для главного окна.
|
||
|
||
:param parent: Главное окно приложения.
|
||
"""
|
||
parent.addDockWidget(Qt.RightDockWidgetArea, self._operator_dock)
|
||
parent.addDockWidget(Qt.RightDockWidgetArea, self._system_dock)
|
||
parent.addDockWidget(Qt.RightDockWidgetArea, self._report_dock)
|
||
parent.addDockWidget(Qt.RightDockWidgetArea, self._filter_dock)
|
||
parent.setMenuBar(self)
|
||
|
||
def _build_dock_widgets(self) -> None:
|
||
"""
|
||
Инициализирует док-виджеты для настроек и скрывает их по умолчанию.
|
||
"""
|
||
# Док-виджет для настроек оператора
|
||
self._operator_dock = QDockWidget("Operator Settings", self)
|
||
self._operator_dock.setWidget(self._operator_settings)
|
||
self._operator_dock.setObjectName("OperatorSettings")
|
||
self._operator_dock.hide()
|
||
|
||
# Док-виджет для системных настроек
|
||
self._system_dock = QDockWidget("System Settings", self)
|
||
self._system_dock.setWidget(self._system_settings)
|
||
self._system_dock.setObjectName("SystemSettings")
|
||
self._system_dock.hide()
|
||
|
||
# Док-виджет для настроек представления отчёта
|
||
self._report_dock = QDockWidget("View settings", self)
|
||
self._report_dock.setWidget(self._report_settings)
|
||
self._report_dock.setObjectName("ReportSettings")
|
||
self._report_dock.hide()
|
||
|
||
# Док-виджет для фильтр-настроек
|
||
self._filter_dock = QDockWidget("Filter settings", self)
|
||
self._filter_dock.setWidget(self._filter_settings)
|
||
self._filter_dock.setObjectName("FilterSetting")
|
||
self._filter_dock.hide()
|
||
|
||
# Устанавливаем функциональные возможности для каждого док-виджета
|
||
self._set_dock_features(self._operator_dock)
|
||
self._set_dock_features(self._system_dock)
|
||
self._set_dock_features(self._report_dock)
|
||
self._set_dock_features(self._filter_dock)
|
||
|
||
def _build_menu(self) -> None:
|
||
"""
|
||
Инициализирует элементы главного меню.
|
||
"""
|
||
# Создаем меню для выбора режима и настроек
|
||
modes_menu = self.addMenu("Mode")
|
||
settings_menu = self.addMenu("Settings")
|
||
|
||
# Действия для переключения режимов
|
||
self.action_scanning = QAction("Real time folder scanning", self)
|
||
self.action_report = QAction("Raport editor", self)
|
||
self.action_client = QAction("Client trace processor", self)
|
||
|
||
# Действия для настроек
|
||
system_settings_action = QAction("System settings", self)
|
||
system_settings_action.setIcon(QIcon('resources/system_ico.png'))
|
||
system_settings_action.triggered.connect(lambda: self._toggle_visibility(self._system_dock))
|
||
|
||
operator_settings_action = QAction("Operator settings", self)
|
||
operator_settings_action.setIcon(QIcon('resources/operator_ico.png'))
|
||
operator_settings_action.triggered.connect(lambda: self._toggle_visibility(self._operator_dock))
|
||
|
||
self.action_view_settings = QAction("View settings", self)
|
||
self.action_view_settings.setIcon(QIcon('resources/view_ico.png'))
|
||
self.action_view_settings.triggered.connect(lambda: self._toggle_visibility(self._report_dock))
|
||
|
||
self.action_filter_settings = QAction("Filter settings", self)
|
||
self.action_filter_settings.triggered.connect(lambda: self._toggle_visibility(self._filter_dock))
|
||
|
||
# Добавляем действия в меню "Mode"
|
||
modes_menu.addAction(self.action_scanning)
|
||
modes_menu.addAction(self.action_report)
|
||
modes_menu.addAction(self.action_client)
|
||
|
||
# Добавляем действия в меню "Settings"
|
||
settings_menu.addAction(system_settings_action)
|
||
settings_menu.addAction(operator_settings_action)
|
||
settings_menu.addAction(self.action_view_settings)
|
||
settings_menu.addAction(self.action_filter_settings)
|
||
|
||
def _toggle_visibility(self, dock: QDockWidget = None) -> None:
|
||
"""
|
||
Переключает видимость указанного док-виджета.
|
||
|
||
:param dock: Док-виджет для переключения.
|
||
"""
|
||
if dock:
|
||
is_visible = dock.isVisible()
|
||
dock.setVisible(not is_visible)
|
||
|
||
@staticmethod
|
||
def _set_dock_features(dock: QDockWidget = None) -> None:
|
||
"""
|
||
Устанавливает возможность перемещения, закрытия и открепления для док-виджета.
|
||
|
||
:param dock: Док-виджет для настройки.
|
||
"""
|
||
if dock:
|
||
features = QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable
|
||
dock.setFeatures(features)
|
||
|
||
|
||
class RaportWidget(QWidget):
|
||
"""
|
||
Виджет для режима редактирования отчёта.
|
||
|
||
Содержит вкладки и кнопки для сохранения состояния и открытия файла.
|
||
"""
|
||
|
||
def __init__(self, tab_widget: CustomTabWidget):
|
||
super().__init__()
|
||
self._tab_widget = tab_widget
|
||
self._build_widget()
|
||
|
||
def get_widget(self) -> QWidget:
|
||
"""
|
||
Возвращает виджет.
|
||
"""
|
||
return self
|
||
|
||
def _build_widget(self) -> None:
|
||
"""
|
||
Строит макет виджета с вкладками и кнопками управления.
|
||
"""
|
||
main_layout = QVBoxLayout()
|
||
self.btn_save_state = QPushButton("Save state")
|
||
self.btn_save_state.setFixedWidth(185)
|
||
self.btn_open_file = QPushButton("Open file")
|
||
self.btn_open_file.setFixedWidth(185)
|
||
|
||
button_layout = QHBoxLayout()
|
||
button_layout.setSpacing(2)
|
||
button_layout.addWidget(self.btn_save_state)
|
||
button_layout.addWidget(self.btn_open_file)
|
||
button_container = QWidget()
|
||
button_container.setLayout(button_layout)
|
||
|
||
main_layout.addWidget(self._tab_widget)
|
||
main_layout.addWidget(button_container)
|
||
self.setLayout(main_layout)
|
||
|
||
|
||
class SeekingWidget(QWidget):
|
||
"""
|
||
Виджет для режима поиска (сканирования папок).
|
||
|
||
"""
|
||
|
||
def __init__(self, tab_widget: CustomTabWidget):
|
||
super().__init__()
|
||
self._tab_widget = tab_widget
|
||
self._build_widget()
|
||
|
||
def get_widget(self) -> QWidget:
|
||
"""
|
||
Возвращает виджет.
|
||
"""
|
||
return self
|
||
|
||
def _build_widget(self) -> None:
|
||
"""
|
||
Создает макет виджета с вкладками.
|
||
"""
|
||
main_layout = QVBoxLayout()
|
||
button_layout = QHBoxLayout()
|
||
button_layout.setSpacing(2)
|
||
button_container = QWidget()
|
||
button_container.setLayout(button_layout)
|
||
|
||
main_layout.addWidget(self._tab_widget)
|
||
main_layout.addWidget(button_container)
|
||
self.setLayout(main_layout)
|
||
|
||
|
||
class ClientAnalyzerWidget(QWidget):
|
||
"""
|
||
Виджет для клиентского анализа трассировки.
|
||
|
||
Содержит вкладки и кнопки для сохранения состояния, открытия папки и расчёта TCW.
|
||
"""
|
||
|
||
def __init__(self, tab_widget: CustomTabWidget):
|
||
super().__init__()
|
||
self._tab_widget = tab_widget
|
||
self._build_widget()
|
||
|
||
def get_widget(self) -> QWidget:
|
||
"""
|
||
Возвращает виджет.
|
||
"""
|
||
return self
|
||
|
||
def _build_widget(self) -> None:
|
||
"""
|
||
Строит макет виджета с вкладками и управляющими кнопками.
|
||
"""
|
||
main_layout = QVBoxLayout()
|
||
self.btn_save_state = QPushButton("Save state")
|
||
self.btn_save_state.setFixedWidth(185)
|
||
self.btn_open_folder = QPushButton("Open folder")
|
||
self.btn_open_folder.setFixedWidth(185)
|
||
self.btn_calc_tcw = QPushButton("Calculate TCW")
|
||
self.btn_calc_tcw.setFixedWidth(185)
|
||
|
||
button_layout = QHBoxLayout()
|
||
button_layout.setSpacing(2)
|
||
button_layout.addWidget(self.btn_save_state)
|
||
button_layout.addWidget(self.btn_open_folder)
|
||
button_layout.addWidget(self.btn_calc_tcw)
|
||
button_container = QWidget()
|
||
button_container.setLayout(button_layout)
|
||
|
||
main_layout.addWidget(self._tab_widget)
|
||
main_layout.addWidget(button_container)
|
||
self.setLayout(main_layout)
|