WeldingSpotPerformance/src/gui/settings_window.py

189 lines
7.1 KiB
Python
Raw Normal View History

from typing import Callable, Optional, Any
from PyQt5.QtWidgets import (
QWidget, QPushButton, QLineEdit, QHBoxLayout, QVBoxLayout, QLabel, QTableWidget, QTableWidgetItem
)
from PyQt5.QtGui import QIntValidator
2024-12-05 13:18:53 +03:00
from utils.json_tools import read_json, write_json
from gui import qt_settings as qts
class settingsWindow(QWidget):
def __init__(self, path: str, name: str, upd_func: Callable[[], None]):
"""
Окно настроек для редактирования параметров.
:param path: Путь к файлу настроек (JSON).
:param name: Название набора настроек.
:param upd_func: Функция обновления (коллбэк).
"""
super().__init__()
self._settingsPath = path
self._name = name
self._data: dict[str, list[Any]] = {}
self._upd_func = upd_func
self._num_points: Optional[QLineEdit] = None
self._param_table: Optional[QTableWidget] = None
self.load_settings()
self._init_ui()
def load_settings(self) -> None:
"""Загружает настройки из JSON-файла."""
data = read_json(self._settingsPath)
if isinstance(data, dict):
self._data = data
else:
self._data = {}
def write_settings(self) -> None:
"""Записывает текущие настройки в JSON-файл."""
write_json(self._settingsPath, self._data)
def getParams(self) -> dict:
"""Возвращает текущий словарь параметров."""
return self._data
def _init_ui(self) -> None:
"""Инициализирует UI: кнопки, поля ввода, таблицу."""
save_button = QPushButton("Save")
restore_button = QPushButton("Restore")
self._num_points = QLineEdit()
self._num_points.setPlaceholderText("Enter the number of welding points")
self._num_points.setValidator(QIntValidator())
control_layout = QHBoxLayout()
control_layout.addWidget(save_button)
control_layout.addWidget(restore_button)
control_layout.addWidget(self._num_points)
save_button.pressed.connect(self._save)
restore_button.pressed.connect(self._restore)
self._num_points.editingFinished.connect(self._expand)
self._param_table = QTableWidget()
self._populate_table()
layout = QVBoxLayout()
header = QLabel(self._name)
layout.addWidget(header)
layout.addLayout(control_layout)
layout.addWidget(self._param_table)
self.setLayout(layout)
self.setStyleSheet(qts.white_style)
def _populate_table(self) -> None:
"""Заполняет таблицу значениями из self._data."""
# Если нет данных для заполнения
if not self._data:
self._param_table.setRowCount(0)
self._param_table.setColumnCount(0)
return
# Предполагаем, что у всех ключей одинаковая длина списков параметров.
first_key = next(iter(self._data), None)
if first_key is None:
self._param_table.setRowCount(0)
self._param_table.setColumnCount(0)
return
column_count = len(self._data[first_key]) + 1
self._param_table.setRowCount(len(self._data))
self._param_table.setColumnCount(column_count)
for i, (key, items) in enumerate(self._data.items()):
self._param_table.setItem(i, 0, QTableWidgetItem(key))
for j, item in enumerate(items):
self._param_table.setItem(i, j+1, QTableWidgetItem(str(item)))
def _save(self) -> None:
"""Сохраняет текущие параметры из таблицы в self._data и вызывает _upd_func()."""
new_data = {}
row_count = self._param_table.rowCount()
col_count = self._param_table.columnCount()
for i in range(row_count):
key_item = self._param_table.item(i, 0)
if key_item is None:
continue
key = key_item.text()
# Если ключ пустой, пропускаем
if not key:
continue
row_data = []
for j in range(1, col_count):
cell_item = self._param_table.item(i, j)
if cell_item is None:
continue
param_str = cell_item.text()
# Если ключ не trace_storage_path, конвертируем в float
if key != "trace_storage_path":
try:
param = float(param_str)
except ValueError:
param = 0.0
else:
param = param_str
row_data.append(param)
new_data[key] = row_data
self._data = new_data
self.write_settings()
self._upd_func()
def _restore(self) -> None:
"""Перезагружает данные из файла и обновляет таблицу."""
self.load_settings()
self._populate_table()
def _expand(self) -> None:
"""Расширяет количество столбцов таблицы в зависимости от введённого значения."""
if not self._num_points:
return
num_points_text = self._num_points.text()
if not num_points_text.isdigit():
return
num_points = int(num_points_text)
if num_points < 0:
return
prev_columns = self._param_table.columnCount()
desired_columns = num_points + 1
if desired_columns <= prev_columns:
return
self._param_table.setColumnCount(desired_columns)
# Новые столбцы заполняем последним известным параметром для каждого ключа
for i, (key, items) in enumerate(self._data.items()):
# Если нет данных, пропускаем
if not items:
continue
last_value = str(items[-1])
for col in range(prev_columns, desired_columns):
self._param_table.setItem(i, col, QTableWidgetItem(last_value))
# Добавляем новый элемент также в self._data для консистентности
# После этого можно будет сохранить при нажатии Save
# Дополним также и в self._data
additional_count = desired_columns - prev_columns
self._data[key].extend([float(last_value) if key != "trace_storage_path" else last_value] * additional_count)
if __name__ == '__main__':
import pyqtgraph as pg
app = pg.mkQApp("Parameter Tree Example")
window = settingsWindow('params\operator_params.json', 'operator')
app.exec()