初始化
This commit is contained in:
597
tools/ui/tabs/config_editor_dialog.py
Normal file
597
tools/ui/tabs/config_editor_dialog.py
Normal file
@@ -0,0 +1,597 @@
|
||||
# --- START OF FILE config_editor_dialog_visual.py ---
|
||||
import json
|
||||
import os
|
||||
from PyQt6.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QTextEdit,
|
||||
QPushButton, QFileDialog, QMessageBox, QLabel,
|
||||
QListWidget, QListWidgetItem, QStackedWidget,
|
||||
QWidget, QTableWidget, QTableWidgetItem,
|
||||
QHeaderView, QSizePolicy, QSplitter, QGroupBox, QGridLayout,
|
||||
QLineEdit, QInputDialog) # Added QInputDialog
|
||||
from PyQt6.QtCore import Qt
|
||||
|
||||
|
||||
class ConfigEditorDialogVisual(QDialog):
|
||||
"""
|
||||
用于可视化编辑JSON配置文件的模态对话框
|
||||
"""
|
||||
def __init__(self, config_file_path, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("编辑配置文件 (可视化)")
|
||||
self.resize(800, 600)
|
||||
|
||||
self.config_file_path = config_file_path
|
||||
self._config_data = {} # Internal dictionary to hold the parsed JSON
|
||||
self.original_content_hash = None # To track changes
|
||||
|
||||
self.init_ui()
|
||||
self.load_config_data()
|
||||
|
||||
# Connect signals after UI is initialized and data is loaded
|
||||
self.parameter_list_widget.currentItemChanged.connect(self._load_parameter_details)
|
||||
self._load_parameter_details(self.parameter_list_widget.currentItem(), None) # Load initial item details if any
|
||||
|
||||
def init_ui(self):
|
||||
"""初始化界面"""
|
||||
main_layout = QVBoxLayout(self)
|
||||
|
||||
# Splitter for parameter list on the left and details on the right
|
||||
splitter = QSplitter(Qt.Orientation.Horizontal)
|
||||
main_layout.addWidget(splitter)
|
||||
|
||||
# Left Panel: Parameter List
|
||||
left_widget = QWidget()
|
||||
left_layout = QVBoxLayout(left_widget)
|
||||
left_layout.addWidget(QLabel("参数列表:"))
|
||||
self.parameter_list_widget = QListWidget()
|
||||
left_layout.addWidget(self.parameter_list_widget)
|
||||
|
||||
# Buttons for adding/removing parameters
|
||||
param_btn_layout = QHBoxLayout()
|
||||
self.add_param_btn = QPushButton("添加参数")
|
||||
self.remove_param_btn = QPushButton("移除参数")
|
||||
param_btn_layout.addWidget(self.add_param_btn)
|
||||
param_btn_layout.addWidget(self.remove_param_btn)
|
||||
left_layout.addLayout(param_btn_layout)
|
||||
|
||||
self.add_param_btn.clicked.connect(self._add_parameter)
|
||||
self.remove_param_btn.clicked.connect(self._remove_parameter)
|
||||
|
||||
|
||||
splitter.addWidget(left_widget)
|
||||
|
||||
# Right Panel: Parameter Details (StackedWidget to potentially show empty state)
|
||||
self.details_stack = QStackedWidget()
|
||||
self.empty_details_widget = QLabel("请从左侧选择一个参数或添加新参数")
|
||||
self.empty_details_widget.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.details_stack.addWidget(self.empty_details_widget) # Index 0
|
||||
|
||||
self.parameter_details_widget = QWidget()
|
||||
self._setup_parameter_details_ui(self.parameter_details_widget)
|
||||
self.details_stack.addWidget(self.parameter_details_widget)
|
||||
|
||||
|
||||
splitter.addWidget(self.details_stack)
|
||||
|
||||
# Set initial sizes for splitter panes
|
||||
splitter.setSizes([200, 600])
|
||||
|
||||
# Bottom Buttons
|
||||
button_layout = QHBoxLayout()
|
||||
self.save_btn = QPushButton("保存")
|
||||
self.save_as_btn = QPushButton("另存为...")
|
||||
self.cancel_btn = QPushButton("取消")
|
||||
|
||||
self.save_btn.clicked.connect(self.save_config)
|
||||
self.save_as_btn.clicked.connect(self.save_config_as)
|
||||
self.cancel_btn.clicked.connect(self.reject)
|
||||
|
||||
button_layout.addWidget(self.save_btn)
|
||||
button_layout.addWidget(self.save_as_btn)
|
||||
button_layout.addStretch()
|
||||
button_layout.addWidget(self.cancel_btn)
|
||||
|
||||
main_layout.addLayout(button_layout)
|
||||
|
||||
# Initial state: Disable save buttons until something is loaded/changed
|
||||
self.save_btn.setEnabled(False)
|
||||
self.save_as_btn.setEnabled(False)
|
||||
self.remove_param_btn.setEnabled(False)
|
||||
|
||||
|
||||
def _setup_parameter_details_ui(self, parent_widget):
|
||||
"""Setup the UI for the parameter details panel"""
|
||||
layout = QVBoxLayout(parent_widget)
|
||||
|
||||
# Fixed fields
|
||||
fixed_fields_group = QGroupBox("基本信息")
|
||||
fixed_fields_layout = QGridLayout(fixed_fields_group)
|
||||
|
||||
self.name_edit = QTextEdit()
|
||||
self.name_edit.setFixedHeight(40) # Allow multi-line but not too tall
|
||||
self.method_edit = QTextEdit()
|
||||
self.method_edit.setFixedHeight(40)
|
||||
self.param_level_edit = QTextEdit()
|
||||
self.param_level_edit.setFixedHeight(40)
|
||||
self.standard_edit = QTextEdit()
|
||||
self.standard_edit.setFixedHeight(40)
|
||||
|
||||
fixed_fields_layout.addWidget(QLabel("项目名称:"), 0, 0)
|
||||
fixed_fields_layout.addWidget(self.name_edit, 0, 1)
|
||||
fixed_fields_layout.addWidget(QLabel("分析方法:"), 1, 0)
|
||||
fixed_fields_layout.addWidget(self.method_edit, 1, 1)
|
||||
fixed_fields_layout.addWidget(QLabel("项目分级:"), 2, 0)
|
||||
fixed_fields_layout.addWidget(self.param_level_edit, 2, 1)
|
||||
fixed_fields_layout.addWidget(QLabel("分级标准名称:"), 3, 0) # Renamed for clarity
|
||||
fixed_fields_layout.addWidget(self.standard_edit, 3, 1)
|
||||
|
||||
layout.addWidget(fixed_fields_group)
|
||||
|
||||
# Standard Levels Table
|
||||
levels_group = QGroupBox("标准等级")
|
||||
levels_layout = QVBoxLayout(levels_group)
|
||||
|
||||
self.levels_table = QTableWidget(0, 2)
|
||||
self.levels_table.setHorizontalHeaderLabels(["等级名称 (Key)", "标准值 (Value)"])
|
||||
self.levels_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
|
||||
self.levels_table.verticalHeader().setVisible(False)
|
||||
levels_layout.addWidget(self.levels_table)
|
||||
|
||||
# Buttons for adding/removing levels
|
||||
level_btn_layout = QHBoxLayout()
|
||||
self.add_level_btn = QPushButton("添加等级")
|
||||
self.remove_level_btn = QPushButton("移除等级")
|
||||
level_btn_layout.addWidget(self.add_level_btn)
|
||||
level_btn_layout.addWidget(self.remove_level_btn)
|
||||
levels_layout.addLayout(level_btn_layout)
|
||||
|
||||
self.add_level_btn.clicked.connect(self._add_standard_level)
|
||||
self.remove_level_btn.clicked.connect(self._remove_standard_level)
|
||||
|
||||
|
||||
layout.addWidget(levels_group)
|
||||
|
||||
layout.addStretch() # Push everything to the top
|
||||
|
||||
# Connect signals for tracking changes (set dirty flag)
|
||||
self.name_edit.textChanged.connect(self._set_dirty)
|
||||
self.method_edit.textChanged.connect(self._set_dirty)
|
||||
self.param_level_edit.textChanged.connect(self._set_dirty)
|
||||
self.standard_edit.textChanged.connect(self._set_dirty)
|
||||
self.levels_table.cellChanged.connect(self._set_dirty)
|
||||
# Adding/removing items/levels also makes it dirty
|
||||
self.add_param_btn.clicked.connect(self._set_dirty)
|
||||
self.remove_param_btn.clicked.connect(self._set_dirty)
|
||||
self.add_level_btn.clicked.connect(self._set_dirty)
|
||||
self.remove_level_btn.clicked.connect(self._set_dirty)
|
||||
|
||||
|
||||
def load_config_data(self):
|
||||
"""加载文件内容到内部字典并填充UI"""
|
||||
self._config_data = {} # Clear previous data
|
||||
self.parameter_list_widget.clear()
|
||||
|
||||
if not self.config_file_path or not os.path.exists(self.config_file_path):
|
||||
QMessageBox.warning(self, "加载错误", f"配置文件不存在或路径无效:\n{self.config_file_path}")
|
||||
self.details_stack.setCurrentIndex(0) # Show empty message
|
||||
return
|
||||
|
||||
try:
|
||||
with open(self.config_file_path, 'r', encoding='utf-8') as f:
|
||||
self._config_data = json.load(f)
|
||||
# Store a hash or string representation for change detection
|
||||
# Use json.dumps to handle ordering consistency
|
||||
self.original_content_hash = hash(json.dumps(self._config_data, sort_keys=True, ensure_ascii=False))
|
||||
|
||||
# Populate the list widget from the loaded data
|
||||
if "export_config" in self._config_data and isinstance(self._config_data["export_config"], dict):
|
||||
for key in sorted(self._config_data["export_config"].keys()):
|
||||
self.parameter_list_widget.addItem(key)
|
||||
|
||||
if self.parameter_list_widget.count() > 0:
|
||||
self.parameter_list_widget.setCurrentRow(0)
|
||||
self.details_stack.setCurrentIndex(1)
|
||||
else:
|
||||
self.details_stack.setCurrentIndex(0)
|
||||
|
||||
else:
|
||||
QMessageBox.warning(self, "加载错误", "配置文件缺少 'export_config' 键或格式不正确。")
|
||||
self.details_stack.setCurrentIndex(0)
|
||||
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
QMessageBox.critical(self, "加载错误", f"配置文件JSON格式无效:\n{e}")
|
||||
self._config_data = {}
|
||||
self.details_stack.setCurrentIndex(0)
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "加载错误", f"无法读取或解析配置文件:\n{str(e)}")
|
||||
self._config_data = {}
|
||||
self.details_stack.setCurrentIndex(0)
|
||||
|
||||
|
||||
def _load_parameter_details(self, current_item, previous_item):
|
||||
"""Load details of the newly selected parameter"""
|
||||
# Before loading new details, save changes from the previous item
|
||||
if previous_item:
|
||||
self._save_parameter_details(previous_item.text())
|
||||
|
||||
# Clear the details UI
|
||||
self.name_edit.clear()
|
||||
self.method_edit.clear()
|
||||
self.param_level_edit.clear()
|
||||
self.standard_edit.clear()
|
||||
self.levels_table.setRowCount(0) # Clear table
|
||||
|
||||
if current_item:
|
||||
key = current_item.text()
|
||||
param_data = self._config_data.get("export_config", {}).get(key, {})
|
||||
|
||||
self.name_edit.setPlainText(param_data.get("项目名称", ""))
|
||||
self.method_edit.setPlainText(param_data.get("分析方法", ""))
|
||||
self.param_level_edit.setPlainText(param_data.get("项目分级", ""))
|
||||
self.standard_edit.setPlainText(param_data.get("分级标准", ""))
|
||||
|
||||
# Load standard levels into the table
|
||||
levels = param_data.get("标准等级", {})
|
||||
if isinstance(levels, dict):
|
||||
self.levels_table.setRowCount(len(levels))
|
||||
# Sort levels by key (等级一, 等级二, etc.) for consistency
|
||||
# for i, (level_key, level_value) in enumerate(sort(levels.items())):
|
||||
for i, (level_key, level_value) in enumerate(levels.items()):
|
||||
self.levels_table.setItem(i, 0, QTableWidgetItem(str(level_key)))
|
||||
self.levels_table.setItem(i, 1, QTableWidgetItem(str(level_value).replace("\n", "\\n")))
|
||||
else:
|
||||
print(f"警告: 参数 '{key}' 的 '标准等级' 不是一个有效的字典。")
|
||||
|
||||
|
||||
self.details_stack.setCurrentIndex(1)
|
||||
self.remove_param_btn.setEnabled(True)
|
||||
self._set_dirty(False)
|
||||
|
||||
else:
|
||||
self.details_stack.setCurrentIndex(0)
|
||||
self.remove_param_btn.setEnabled(False)
|
||||
self._set_dirty(False)
|
||||
|
||||
|
||||
def _save_parameter_details(self, key):
|
||||
"""Save details from the UI widgets back to the internal dictionary for the given key"""
|
||||
if not key or "export_config" not in self._config_data or key not in self._config_data["export_config"]:
|
||||
return # Nothing to save if key is invalid or not in data
|
||||
|
||||
param_data = self._config_data["export_config"][key]
|
||||
|
||||
param_data["项目名称"] = self.name_edit.toPlainText()
|
||||
param_data["分析方法"] = self.method_edit.toPlainText()
|
||||
param_data["项目分级"] = self.param_level_edit.toPlainText()
|
||||
param_data["分级标准"] = self.standard_edit.toPlainText()
|
||||
|
||||
# Save standard levels from the table
|
||||
levels = {}
|
||||
for row in range(self.levels_table.rowCount()):
|
||||
key_item = self.levels_table.item(row, 0)
|
||||
value_item = self.levels_table.item(row, 1)
|
||||
if key_item and value_item:
|
||||
level_key = key_item.text().strip()
|
||||
level_value = value_item.text().strip().replace("\\n", "\n")
|
||||
if level_key: # Only save if level key is not empty
|
||||
levels[level_key] = level_value
|
||||
else:
|
||||
print(f"警告: 参数 '{key}' 中存在空的等级名称,该行将被忽略。")
|
||||
|
||||
param_data["标准等级"] = levels
|
||||
# print(f"Saved details for parameter: {key}") # Debugging
|
||||
|
||||
|
||||
def _add_parameter(self):
|
||||
"""Add a new parameter item"""
|
||||
key, ok = QInputDialog.getText(self, "添加新参数", "输入新的参数键 (例如: NEW):")
|
||||
if ok and key:
|
||||
key = key.strip()
|
||||
if not key:
|
||||
QMessageBox.warning(self, "输入错误", "参数键不能为空。")
|
||||
return
|
||||
if "export_config" not in self._config_data:
|
||||
self._config_data["export_config"] = {}
|
||||
|
||||
if key in self._config_data["export_config"]:
|
||||
QMessageBox.warning(self, "输入错误", f"参数键 '{key}' 已存在。")
|
||||
return
|
||||
|
||||
# Add a default structure for the new parameter
|
||||
self._config_data["export_config"][key] = {
|
||||
"项目名称": "新项目名称",
|
||||
"分析方法": "新分析方法",
|
||||
"项目分级": "新项目分级",
|
||||
"分级标准": "新分级标准",
|
||||
"标准等级": {}
|
||||
}
|
||||
|
||||
# Add to list widget and select it
|
||||
self.parameter_list_widget.addItem(key)
|
||||
# Re-sort the list
|
||||
self.parameter_list_widget.sortItems()
|
||||
# Find and select the new item
|
||||
items = self.parameter_list_widget.findItems(key, Qt.MatchFlag.MatchExactly)
|
||||
if items:
|
||||
self.parameter_list_widget.setCurrentItem(items[0])
|
||||
|
||||
self._set_dirty()
|
||||
|
||||
|
||||
def _remove_parameter(self):
|
||||
"""Remove the currently selected parameter item"""
|
||||
current_item = self.parameter_list_widget.currentItem()
|
||||
if not current_item:
|
||||
return # Nothing selected
|
||||
|
||||
key_to_remove = current_item.text()
|
||||
reply = QMessageBox.question(
|
||||
self, "移除参数", f"确定要移除参数 '{key_to_remove}' 吗?\n此操作不可撤销。",
|
||||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
||||
)
|
||||
|
||||
if reply == QMessageBox.StandardButton.Yes:
|
||||
# Save details of the item being removed *before* removing it from data
|
||||
# (This handles case where user edits an item then immediately removes it)
|
||||
self._save_parameter_details(key_to_remove)
|
||||
|
||||
# Remove from internal data
|
||||
if "export_config" in self._config_data and key_to_remove in self._config_data["export_config"]:
|
||||
del self._config_data["export_config"][key_to_remove]
|
||||
|
||||
# Remove from list widget
|
||||
row = self.parameter_list_widget.row(current_item)
|
||||
self.parameter_list_widget.takeItem(row)
|
||||
|
||||
# Clear details panel and maybe select next item or show empty
|
||||
self._load_parameter_details(self.parameter_list_widget.currentItem(), current_item)
|
||||
self._set_dirty()
|
||||
|
||||
|
||||
def _add_standard_level(self):
|
||||
"""Add a new row to the standard levels table"""
|
||||
current_item = self.parameter_list_widget.currentItem()
|
||||
if not current_item:
|
||||
QMessageBox.warning(self, "添加等级", "请先选择一个参数。")
|
||||
return
|
||||
|
||||
row_count = self.levels_table.rowCount()
|
||||
self.levels_table.insertRow(row_count)
|
||||
# Add default items (editable)
|
||||
self.levels_table.setItem(row_count, 0, QTableWidgetItem("新等级"))
|
||||
self.levels_table.setItem(row_count, 1, QTableWidgetItem(""))
|
||||
|
||||
self._set_dirty()
|
||||
|
||||
|
||||
def _remove_standard_level(self):
|
||||
"""Remove selected rows from the standard levels table"""
|
||||
# selected_rows = sorted(list(set(index.row() for index in self.levels_table.selectedIndexes())), reverse=True)
|
||||
selected_rows = list(set(index.row() for index in self.levels_table.selectedIndexes()))
|
||||
if not selected_rows:
|
||||
QMessageBox.warning(self, "移除等级", "请选择要移除的等级行。")
|
||||
return
|
||||
|
||||
for row in selected_rows:
|
||||
self.levels_table.removeRow(row)
|
||||
|
||||
self._set_dirty()
|
||||
|
||||
|
||||
def _set_dirty(self, dirty=True):
|
||||
"""Set or clear the dirty flag and update button states"""
|
||||
# This slot might receive a bool from cellChanged, or be called with True/False
|
||||
# Ensure it's treated as a boolean
|
||||
self._is_dirty = bool(dirty)
|
||||
|
||||
# Enable save buttons if dirty
|
||||
self.save_btn.setEnabled(self._is_dirty)
|
||||
self.save_as_btn.setEnabled(True)
|
||||
|
||||
# print(f"Dirty state: {self._is_dirty}") # Debugging
|
||||
|
||||
|
||||
def is_dirty(self):
|
||||
"""Check if the configuration has been modified"""
|
||||
if not self._is_dirty:
|
||||
return False
|
||||
|
||||
# Perform a more thorough check by saving current state to a temp dict
|
||||
# and comparing its hash with the original hash
|
||||
try:
|
||||
# Save details of the currently selected item first
|
||||
current_key = self.parameter_list_widget.currentItem()
|
||||
if current_key:
|
||||
self._save_parameter_details(current_key.text())
|
||||
|
||||
current_hash = hash(json.dumps(self._config_data, sort_keys=True, ensure_ascii=False))
|
||||
return current_hash != self.original_content_hash
|
||||
except Exception as e:
|
||||
print(f"Error checking dirty state: {e}")
|
||||
# If hashing fails, assume it's dirty to be safe
|
||||
return True
|
||||
|
||||
|
||||
def validate_config(self):
|
||||
"""Validate the structure of the internal config data before saving"""
|
||||
if "export_config" not in self._config_data or not isinstance(self._config_data["export_config"], dict):
|
||||
QMessageBox.warning(self, "验证失败", "配置缺少主键 'export_config' 或其格式不正确。")
|
||||
return False
|
||||
|
||||
standards_dict = self._config_data["export_config"]
|
||||
error_keys = []
|
||||
for key, value in standards_dict.items():
|
||||
# Check for required fields and types
|
||||
if not isinstance(value, dict):
|
||||
error_keys.append(f"{key}: 结构不是字典")
|
||||
continue
|
||||
required_keys = ["项目名称", "分析方法", "项目分级", "分级标准", "标准等级"]
|
||||
if not all(k in value for k in required_keys):
|
||||
error_keys.append(f"{key}: 缺少必要字段")
|
||||
continue
|
||||
if not isinstance(value.get("标准等级"), dict):
|
||||
error_keys.append(f"{key}: '标准等级' 不是字典")
|
||||
continue
|
||||
|
||||
if error_keys:
|
||||
QMessageBox.warning(self, "验证失败", "配置文件结构或内容存在问题:\n" + "\n".join(error_keys))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def save_config(self):
|
||||
"""保存配置到当前文件路径"""
|
||||
# Save details of the currently selected item before saving the whole config
|
||||
current_item = self.parameter_list_widget.currentItem()
|
||||
if current_item:
|
||||
self._save_parameter_details(current_item.text())
|
||||
|
||||
if not self.validate_config():
|
||||
return False
|
||||
|
||||
if not self.config_file_path:
|
||||
# If no path is set (e.g., started with no file and added items), force Save As
|
||||
return self.save_config_as()
|
||||
|
||||
return self._perform_save(self.config_file_path)
|
||||
|
||||
|
||||
def save_config_as(self):
|
||||
"""另存配置"""
|
||||
file_path, _ = QFileDialog.getSaveFileName(
|
||||
self, "另存配置文件", self.config_file_path if self.config_file_path else "",
|
||||
"JSON 文件 (*.json);;所有文件 (*)"
|
||||
)
|
||||
if file_path:
|
||||
# Save details of the currently selected item before saving the whole config
|
||||
current_item = self.parameter_list_widget.currentItem()
|
||||
if current_item:
|
||||
self._save_parameter_details(current_item.text())
|
||||
|
||||
if not self.validate_config():
|
||||
return False
|
||||
|
||||
if self._perform_save(file_path):
|
||||
# Update the current file path if Save As was successful
|
||||
self.config_file_path = file_path
|
||||
# Reload from the new path to reset original_content_hash and dirty state
|
||||
self.load_config_data()
|
||||
QMessageBox.information(self, "另存成功", f"配置文件已另存为:\n{self.config_file_path}")
|
||||
self.accept()
|
||||
return True
|
||||
return False
|
||||
return False
|
||||
def _perform_save(self, path):
|
||||
"""Execute the saving of the config data to a file"""
|
||||
try:
|
||||
# Ensure directory exists
|
||||
dir_name = os.path.dirname(path)
|
||||
if dir_name and not os.path.exists(dir_name):
|
||||
os.makedirs(dir_name, exist_ok=True)
|
||||
|
||||
with open(path, 'w', encoding='utf-8') as f:
|
||||
# Use indent=4 for readability and ensure_ascii=False for Chinese chars
|
||||
json.dump(self._config_data, f, indent=4, ensure_ascii=False)
|
||||
|
||||
# Update the original content hash after saving
|
||||
self.original_content_hash = hash(json.dumps(self._config_data, sort_keys=True, ensure_ascii=False))
|
||||
self._set_dirty(False) # Clear dirty flag
|
||||
|
||||
# For standard save, don't close the dialog, just inform
|
||||
# QMessageBox.information(self, "保存成功", f"配置文件已保存:\n{path}") # Removed msgbox for standard save
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "保存失败", f"保存文件时出错:\n{str(e)}")
|
||||
return False
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""Handle close event, ask to save if dirty"""
|
||||
if self.is_dirty():
|
||||
reply = QMessageBox.question(
|
||||
self, "保存更改",
|
||||
"配置文件已修改,是否保存?",
|
||||
QMessageBox.StandardButton.Save | QMessageBox.StandardButton.Discard | QMessageBox.StandardButton.Cancel,
|
||||
QMessageBox.StandardButton.Save
|
||||
)
|
||||
|
||||
if reply == QMessageBox.StandardButton.Save:
|
||||
if self.save_config():
|
||||
event.accept()
|
||||
else:
|
||||
event.ignore()
|
||||
elif reply == QMessageBox.StandardButton.Discard:
|
||||
event.accept()
|
||||
else:
|
||||
event.ignore()
|
||||
else:
|
||||
event.accept()
|
||||
# Method to retrieve the potentially new file path after saving (e.g., Save As)
|
||||
def get_new_config_path(self):
|
||||
return self.config_file_path
|
||||
|
||||
|
||||
# Example running (for testing this dialog itself)
|
||||
if __name__ == '__main__':
|
||||
from PyQt6.QtWidgets import QApplication
|
||||
import sys
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
# Create a dummy config file for testing if it doesn't exist
|
||||
test_dir = "temp_config_editor_test"
|
||||
os.makedirs(test_dir, exist_ok=True)
|
||||
test_config_path = os.path.join(test_dir, "test_config.json")
|
||||
|
||||
dummy_data = {
|
||||
"export_config": {
|
||||
"AB": {
|
||||
"项目名称": "测试硼",
|
||||
"分析方法": "测试方法",
|
||||
"项目分级": "硼级别",
|
||||
"分级标准": "硼标准",
|
||||
"标准等级": {
|
||||
"等级1": ">2.00",
|
||||
"等级2": "1.00~2.00"
|
||||
}
|
||||
},
|
||||
"ZN": {
|
||||
"项目名称": "测试锌",
|
||||
"分析方法": "锌方法",
|
||||
"项目分级": "锌级别",
|
||||
"分级标准": "锌标准",
|
||||
"标准等级": {
|
||||
"A级": ">3.00",
|
||||
"B级": "2.00~3.00",
|
||||
"C级": "<2.00"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if not os.path.exists(test_config_path):
|
||||
try:
|
||||
with open(test_config_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(dummy_data, f, indent=4, ensure_ascii=False)
|
||||
print(f"Created dummy config file: {test_config_path}")
|
||||
except Exception as e:
|
||||
print(f"Error creating dummy file: {e}")
|
||||
test_config_path = "" # Clear path if creation fails
|
||||
|
||||
|
||||
dialog = ConfigEditorDialogVisual(test_config_path)
|
||||
result = dialog.exec()
|
||||
|
||||
if result == QDialog.DialogCode.Accepted:
|
||||
final_path = dialog.get_new_config_path()
|
||||
print(f"Dialog accepted. Final config path: {final_path}")
|
||||
else:
|
||||
print("Dialog rejected or cancelled.")
|
||||
|
||||
# Optional: Clean up test files/directory
|
||||
# import shutil
|
||||
# if os.path.exists(test_dir):
|
||||
# shutil.rmtree(test_dir)
|
||||
|
||||
sys.exit(app.exec())
|
||||
Reference in New Issue
Block a user