Compare commits

...

2 Commits

21 changed files with 188 additions and 83 deletions

BIN
resources/operator_ico.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
resources/system_ico.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
resources/view_ico.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -8,8 +8,10 @@ class Controller(BaseController):
signal_widgets = pyqtSignal(list)
signal_settings = pyqtSignal(list)
signal_raport_mode = pyqtSignal(str)
signal_open_file = pyqtSignal(str)
signal_raport_mode = pyqtSignal()
signal_seeking_mode = pyqtSignal()
signal_update_plots = pyqtSignal()
def send_widgets(self, widgets: list[QWidget]) -> None:
self.signal_widgets.emit(widgets)
@ -17,12 +19,17 @@ class Controller(BaseController):
def update_settings(self, settings: list[dict]) -> None:
self.signal_settings.emit(settings)
def raport_mode(self, filepath: str) -> None:
self.signal_raport_mode.emit(filepath)
def raport_mode(self) -> None:
self.signal_raport_mode.emit()
def seeking_mode(self) -> None:
self.signal_seeking_mode.emit()
def open_file(self, filepath: str) -> None:
self.signal_open_file.emit(filepath)
def update_plots(self) -> None:
self.signal_update_plots.emit()

View File

@ -29,6 +29,5 @@ class Mediator(BaseMediator):
def update_settings(self, settings: list[dict]):
self._monitor.update_settings(settings)
self._passportFormer.update_settings(settings)
self._monitor.update_plots()

View File

@ -51,18 +51,26 @@ class DirectoryMonitor(BaseDirectoryMonitor):
def update_plots(self):
if self._files is not None:
print("updPlot")
self._mediator.notify(self, self._files)
def custom_csv_extract_only(self, path: str):
self.stop()
self._files.append(path)
if path is not None:
self._mediator.notify(self, [path])
else:
self._mediator.notify(self, [None])
def start_raport(self) -> None:
print("startRaport")
self.stop()
self._files = []
print(self._files)
self._mediator.notify(self, [None])
def start_seeking(self) -> None:
print("startSeeking")
self._init_state()
self.start()

View File

@ -2,27 +2,37 @@ from datetime import datetime as dt
from typing import Optional
from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap
from PyQt5.QtGui import QPixmap, QIcon
from utils.base.base import BaseMainWindow, BaseController
from gui.settings_window import SystemSettings, OperatorSettings
from gui.reportGui import ReportSettings
# FIXME: При отркытии RaportMode все прочитанные трейсы должны удаляться, но они открываются...
class MainWindow(BaseMainWindow):
def __init__(self,
controller: Optional[BaseController] = None) -> None:
super().__init__()
self._controller = controller
self._init_startUI()
self._init_dock_widgets()
self._init_menu()
def _init_TabWidget(self) -> None:
self.tabWidget = QtWidgets.QTabWidget()
self.tabWidget.setTabsClosable(True)
self.tabWidget.tabCloseRequested.connect(self._close_tab)
self.tabWidget.currentChanged.connect(self._on_tab_changed)
def _init_startUI(self) -> None:
self.operSettings = OperatorSettings("params/operator_params.json", 'Operator', self._transfer_settings)
self.sysSettings = SystemSettings("params/system_params.json", 'System', self._transfer_settings)
self.repSettings = ReportSettings()
self.tabWidget = QtWidgets.QTabWidget()
self.operSettings = OperatorSettings("params/operator_params.json", 'Operator', self._upd_settings)
self.sysSettings = SystemSettings("params/system_params.json", 'System', self._upd_settings)
self.repSettings = ReportSettings()
self._clear()
self.resize(800,800)
seeking_mode_btn = QtWidgets.QPushButton("Real time folder scanning")
seeking_mode_btn.setFixedWidth(300)
seeking_mode_btn.clicked.connect(self._init_seekingUI)
@ -37,7 +47,7 @@ class MainWindow(BaseMainWindow):
button_widget = QtWidgets.QWidget()
button_widget.setLayout(button_layout)
mainLayout = self.layout()
mainLayout = self._central_layout
label = QtWidgets.QLabel("Select work mode")
label.setStyleSheet(
"""QLabel{
@ -50,61 +60,122 @@ class MainWindow(BaseMainWindow):
mainLayout.addWidget(label, alignment=Qt.AlignCenter)
mainLayout.addWidget(button_widget)
def _init_dock_widgets(self) -> None:
"""
Инициализация док-виджетов для настроек.
"""
# Создаем док-виджет для OperatorSettings
self.operator_dock = QtWidgets.QDockWidget("Operator Settings", self)
self.operator_dock.setWidget(self.operSettings)
self.operator_dock.setObjectName("OperatorSettings")
self.addDockWidget(Qt.RightDockWidgetArea, self.operator_dock)
self.operator_dock.hide() # Скрываем по умолчанию
# Создаем док-виджет для SystemSettings
self.system_dock = QtWidgets.QDockWidget("System Settings", self)
self.system_dock.setWidget(self.sysSettings)
self.system_dock.setObjectName("SystemSettings")
self.addDockWidget(Qt.RightDockWidgetArea, self.system_dock)
self.system_dock.hide() # Скрываем по умолчанию
# Создаем док-виджет для ReportSettings
self.report_dock = QtWidgets.QDockWidget("Report Settings", self)
self.report_dock.setWidget(self.repSettings)
self.report_dock.setObjectName("ReportSettings")
self.addDockWidget(Qt.RightDockWidgetArea, self.report_dock)
self.report_dock.hide() # Скрываем по умолчанию
# Настройка док-виджетов
self._set_dock_features(self.operator_dock)
self._set_dock_features(self.system_dock)
self._set_dock_features(self.report_dock)
def _init_menu(self) -> None:
"""
Инициализация главного меню.
"""
# Создаем главное меню
menu_bar = self.menuBar()
# Создаем меню "Режимы"
modes_menu = menu_bar.addMenu("Mode")
settings_menu = menu_bar.addMenu("Settings")
# Создаем действия для меню
seeking_action = QtWidgets.QAction("Real time folder scanning", self)
seeking_action.triggered.connect(self._init_seekingUI)
raport_action = QtWidgets.QAction("Raport editor", self)
raport_action.triggered.connect(self._init_raportUI)
system_settings = QtWidgets.QAction("System settings", self)
system_settings.setIcon(QIcon('resources/system_ico.png'))
system_settings.triggered.connect(lambda: self._toggle_visibility(self.system_dock))
operator_settings = QtWidgets.QAction("Operator settings", self)
operator_settings.setIcon(QIcon('resources/operator_ico.png'))
operator_settings.triggered.connect(lambda: self._toggle_visibility(self.operator_dock))
view_settings = QtWidgets.QAction("View settings", self)
view_settings.setIcon(QIcon('resources/view_ico.png'))
view_settings.triggered.connect(lambda: self._toggle_visibility(self.report_dock))
# Добавляем действия в меню "Режимы"
modes_menu.addAction(seeking_action)
modes_menu.addAction(raport_action)
settings_menu.addAction(system_settings)
settings_menu.addAction(operator_settings)
settings_menu.addAction(view_settings)
def _toggle_visibility(self, body:QtWidgets.QDockWidget = None) -> None:
"""
Переключение видимости док-виджета.
"""
is_visible = body.isVisible()
body.setVisible(not is_visible)
def _set_dock_features(self, body:QtWidgets.QDockWidget = None) -> None:
"""
Настройка флагов док-виджета.
"""
flag_move = QtWidgets.QDockWidget.DockWidgetMovable
flag_close = QtWidgets.QDockWidget.DockWidgetClosable
flag_floating = QtWidgets.QDockWidget.DockWidgetFloatable
body.setFeatures(flag_move | flag_close | flag_floating)
def _clear(self) -> None:
main = self.layout()
if self.layout() is not None:
while main.count():
child = main.takeAt(0)
if self._central_layout is not None:
while self._central_layout.count():
child = self._central_layout.takeAt(0)
if child.widget() is not None:
child.widget().deleteLater()
else: self.setLayout(QtWidgets.QVBoxLayout())
def _init_seekingUI(self) -> None:
self._clear()
self._init_TabWidget()
self._transfer_settings()
self.tabWidget = QtWidgets.QTabWidget()
self.tabWidget.setTabsClosable(True)
self.tabWidget.tabCloseRequested.connect(self._close_tab)
sys_settings_btn = QtWidgets.QPushButton("System settings")
sys_settings_btn.setFixedWidth(200)
sys_settings_btn.clicked.connect(lambda: self.sysSettings.show())
oper_settings_btn = QtWidgets.QPushButton("Operator settings")
oper_settings_btn.setFixedWidth(200)
oper_settings_btn.clicked.connect(lambda: self.operSettings.show())
button_layout = QtWidgets.QHBoxLayout()
button_layout.setSpacing(2)
button_layout.addWidget(sys_settings_btn)
button_layout.addWidget(oper_settings_btn)
button_widget = QtWidgets.QWidget()
button_widget.setLayout(button_layout)
title = QtWidgets.QLabel("online mode")
mainLayout = self.layout()
mainLayout.addWidget(self.tabWidget)
mainLayout.addWidget(button_widget)
mainLayout.addWidget(title, alignment=Qt.AlignRight)
self.resize(800,800)
self._central_layout.addWidget(self.tabWidget)
self._central_layout.addWidget(button_widget)
self._central_layout.addWidget(title, alignment=Qt.AlignRight)
self._controller.seeking_mode()
# TODO:push seeking to mediator
def _init_raportUI(self) -> None:
self._clear()
self._init_TabWidget()
self._transfer_settings()
self.tabWidget = QtWidgets.QTabWidget()
self.tabWidget.setTabsClosable(True)
self.tabWidget.tabCloseRequested.connect(self._close_tab)
sys_settings_btn = QtWidgets.QPushButton("System settings")
sys_settings_btn.setFixedWidth(185)
sys_settings_btn.clicked.connect(lambda: self.sysSettings.show())
oper_settings_btn = QtWidgets.QPushButton("Operator settings")
oper_settings_btn.setFixedWidth(185)
oper_settings_btn.clicked.connect(lambda: self.operSettings.show())
view_settings_btn = QtWidgets.QPushButton("Customize view")
view_settings_btn.setFixedWidth(185)
view_settings_btn.clicked.connect(self._customization_window)
save_screen_btn = QtWidgets.QPushButton("Save state")
save_screen_btn.setFixedWidth(185)
save_screen_btn.clicked.connect(self._save_plots)
@ -114,25 +185,18 @@ class MainWindow(BaseMainWindow):
button_layout = QtWidgets.QHBoxLayout()
button_layout.setSpacing(2)
button_layout.addWidget(sys_settings_btn)
button_layout.addWidget(oper_settings_btn)
button_layout.addWidget(view_settings_btn)
button_layout.addWidget(save_screen_btn)
button_layout.addWidget(open_file_btn)
button_widget = QtWidgets.QWidget()
button_widget.setLayout(button_layout)
title = QtWidgets.QLabel("raport mode")
mainLayout = self.layout()
mainLayout.addWidget(self.tabWidget)
mainLayout.addWidget(button_widget)
mainLayout.addWidget(title, alignment=Qt.AlignRight)
self.resize(800,800)
self._controller.raport_mode(None)
self._central_layout.addWidget(self.tabWidget)
self._central_layout.addWidget(button_widget)
self._central_layout.addWidget(title, alignment=Qt.AlignRight)
#self._controller.raport_mode(path)
# TODO: push only one dir to monitor
self._controller.raport_mode()
def show_plot_tabs(self, plot_widgets: list[QtWidgets.QWidget]) -> None:
for plot_widget in plot_widgets:
@ -149,7 +213,7 @@ class MainWindow(BaseMainWindow):
tab_count = self.tabWidget.count()
if tab_count > 10:
for i in range(0, tab_count-2):
for i in range(0, tab_count-10):
self._close_tab(i)
def keyPressEvent(self, a0) -> None:
@ -164,22 +228,22 @@ class MainWindow(BaseMainWindow):
self.repSettings.close()
super().closeEvent(a0)
def _show_settings(self) -> None:
self.operSettings.show()
self.sysSettings.show()
def _transfer_settings(self) -> None:
self.tabWidget.clear()
operator_params = self.operSettings.getParams()
system_params = self.sysSettings.getParams()
self._controller.update_settings([operator_params, system_params])
def _upd_settings(self) -> None:
self._transfer_settings()
self._controller.update_plots()
def _close_tab(self, index:int) -> None:
self.tabWidget.removeTab(index)
def _open_file(self) -> None:
path = self._select_csv()
self._controller.raport_mode(path)
self._controller.open_file(path)
def _select_csv(self) -> Optional[str]:
CSV_path, _ = QtWidgets.QFileDialog.getOpenFileName(self,"Select csv file", "", "CSV Files (*.csv)")
@ -188,18 +252,20 @@ class MainWindow(BaseMainWindow):
return CSV_path
return None
def _customization_window(self) -> None:
def _on_tab_changed(self, index):
tab = self.tabWidget.currentWidget()
reg_items = tab.property("reg_items")
curve_items = tab.property("curve_items")
self.repSettings.build(reg_items, curve_items)
if tab is not None and self.report_dock.isVisible():
reg_items = tab.property("reg_items")
curve_items = tab.property("curve_items")
self.repSettings.build(index, reg_items, curve_items)
def _save_plots(self) -> None:
filepath, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Save file", "", "Image Files (*.png *.jpeg)")
tab = self.tabWidget.currentWidget()
pixmap = QPixmap(tab.size())
tab.render(pixmap)
pixmap.save(filepath)
if tab is not None:
pixmap = QPixmap(tab.size())
tab.render(pixmap)
pixmap.save(filepath)

View File

@ -2,28 +2,38 @@ import pyqtgraph as pg
from pyqtgraph.parametertree import Parameter, ParameterTree
from typing import Union
from PyQt5 import QtWidgets
from cachetools import LRUCache
class ReportSettings(QtWidgets.QWidget):
def __init__(self, parent = None):
super().__init__(parent)
#self._tab_cashe = LRUCache(maxsize=1000)
def build(self, reg_items: dict, curve_items: dict) -> None:
def build(self, index, reg_items: dict, curve_items: dict) -> None:
"""Создает ParameterTree для элементов всех графиков выбранной вкладки"""
self._clear()
param_tree = ParameterTree()
layout = self.layout()
layout.addWidget(param_tree)
"""if index in self._tab_cashe:
body = self._tab_cashe[index]
else:
body= [
self._generate_reg_params(reg_items),
self._generate_curve_params(curve_items)
]
self._tab_cashe[index] = body"""
body= [
self._generate_reg_params(reg_items),
self._generate_curve_params(curve_items)
]
self._generate_reg_params(reg_items),
self._generate_curve_params(curve_items)
]
# Добавляем параметры в дерево
params = Parameter.create(name='params', type='group', children=body)
params.sigTreeStateChanged.connect(
lambda: self._update_settings(reg_items, curve_items, params)
)
param_tree.setParameters(params, showTop=False)
self.show()
def _clear(self) -> None:
"""

View File

@ -25,8 +25,10 @@ def main():
controller.signal_widgets.connect(window.show_plot_tabs)
controller.signal_settings.connect(mediator.update_settings)
controller.signal_raport_mode.connect(monitor.custom_csv_extract_only)
controller.signal_open_file.connect(monitor.custom_csv_extract_only)
controller.signal_raport_mode.connect(monitor.start_raport)
controller.signal_seeking_mode.connect(monitor.start_seeking)
controller.signal_update_plots.connect(monitor.update_plots)
sys.exit(app.exec_())

View File

@ -6,7 +6,7 @@ from cachetools import LRUCache
import pandas as pd
from PyQt5.QtCore import QObject, QTimer
from PyQt5.QtWidgets import QWidget, QTabWidget
from PyQt5.QtWidgets import QWidget, QTabWidget, QMainWindow, QVBoxLayout
from OptAlgorithm import OptAlgorithm
import numpy as np
import pyqtgraph as pg
@ -343,12 +343,18 @@ class BaseController(QObject):
def update_settings(self, settings: list[dict]) -> None:
...
def raport_mode (self, filepath: str) -> None:
def raport_mode (self) -> None:
...
def seeking_mode(self) -> None:
...
def open_file(self, filepath: str) -> None:
...
def update_plots(self) -> None:
...
class BaseIdealDataBuilder(OptAlgorithm):
def __init__(self, params: list[dict]):
@ -393,13 +399,20 @@ class BaseIdealDataBuilder(OptAlgorithm):
result = sum(self.get_ideal_timings())
return result
class BaseMainWindow(QWidget):
class BaseMainWindow(QMainWindow):
def __init__(self,
controller: Optional[BaseController] = None):
super().__init__()
self.set_style(self)
self.resize(200,200)
self._controller = controller
# Создаем центральный виджет и устанавливаем его
self._central_widget = QWidget()
self.setCentralWidget(self._central_widget)
# Устанавливаем основной вертикальный макет для центрального виджета
self._central_layout = QVBoxLayout()
self._central_widget.setLayout(self._central_layout)
self.set_style(self._central_widget)
...
@property