上传文件至 /
代码优化,新增一键隐藏,取消自动分组 Signed-off-by: hujinyang <hujinyang@pw.com>
This commit is contained in:
parent
7391a4b29b
commit
0a7204f85e
232
build.sh
232
build.sh
@ -1,16 +1,17 @@
|
||||
# config Editor 一键构建脚本
|
||||
|
||||
# config editor 一键构建脚本 - 修复虚拟环境安装问题
|
||||
set -e
|
||||
|
||||
# 配置变量
|
||||
PACKAGE_NAME="config-editor"
|
||||
VERSION="1.0"
|
||||
VERSION="1.1"
|
||||
ARCHITECTURE="amd64"
|
||||
MAINTAINER="hjy <hjy@pw.com>"
|
||||
|
||||
echo "=========================================="
|
||||
echo "Config Editor 构建脚本 (虚拟环境版)"
|
||||
echo "版本: $VERSION"
|
||||
echo "Config Editor 构建脚本 - 版本 $VERSION"
|
||||
echo "架构: $ARCHITECTURE"
|
||||
echo "构建时间: $(date)"
|
||||
echo "=========================================="
|
||||
|
||||
# 检查依赖
|
||||
@ -24,7 +25,6 @@ fi
|
||||
echo "检查源代码..."
|
||||
if [ ! -f "config_editor.py" ]; then
|
||||
echo "错误: 未找到主程序文件 config_editor.py"
|
||||
echo "请确保在项目根目录运行此脚本,且包含 config_editor.py 文件"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -39,58 +39,40 @@ mkdir -p "$BUILD_DIR/usr/bin"
|
||||
|
||||
# 复制应用文件
|
||||
echo "复制应用文件..."
|
||||
echo "复制主程序 config_editor.py"
|
||||
cp config_editor.py "$BUILD_DIR/usr/share/config-editor/"
|
||||
|
||||
# 复制配置文件
|
||||
if [ -f "config_editor_rules.json" ]; then
|
||||
echo "复制配置文件 config_editor_rules.json"
|
||||
cp config_editor_rules.json "$BUILD_DIR/usr/share/config-editor/"
|
||||
else
|
||||
echo "警告: 未找到 config_editor_rules.json 文件"
|
||||
fi
|
||||
|
||||
if [ -f "config_editor_settings.json" ]; then
|
||||
echo "复制配置文件 config_editor_settings.json"
|
||||
cp config_editor_settings.json "$BUILD_DIR/usr/share/config-editor/"
|
||||
else
|
||||
echo "警告: 未找到 config_editor_settings.json 文件"
|
||||
fi
|
||||
|
||||
# 复制所有Python文件
|
||||
echo "复制其他Python文件..."
|
||||
find . -maxdepth 1 -name "*.py" ! -name "build.sh" -exec cp {} "$BUILD_DIR/usr/share/config-editor/" \; 2>/dev/null || true
|
||||
|
||||
# 显示复制的文件
|
||||
echo "已复制的文件:"
|
||||
ls -la "$BUILD_DIR/usr/share/config-editor/"
|
||||
|
||||
# 检查是否复制了真实的应用文件
|
||||
if [ ! -f "$BUILD_DIR/usr/share/config-editor/config_editor.py" ]; then
|
||||
echo "错误: 未成功复制 config_editor.py 文件"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 创建桌面文件
|
||||
echo "创建桌面文件..."
|
||||
cat > "$BUILD_DIR/usr/share/applications/config-editor.desktop" << EOF
|
||||
cat > "$BUILD_DIR/usr/share/applications/config-editor.desktop" << 'EOF'
|
||||
[Desktop Entry]
|
||||
Version=1.1
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Name=Config Editor
|
||||
Comment=Configuration Management System
|
||||
Exec=config-editor
|
||||
Comment=Configuration Management Tool
|
||||
Exec=/usr/bin/config-editor
|
||||
Icon=config-editor
|
||||
Categories=Development;Settings;
|
||||
Categories=Development;Utility;Settings;
|
||||
Terminal=false
|
||||
StartupNotify=true
|
||||
StartupWMClass=ConfigEditor
|
||||
EOF
|
||||
|
||||
# 创建虚拟环境安装脚本(已修复权限问题)
|
||||
# 创建虚拟环境安装脚本 - 修复版本
|
||||
echo "创建虚拟环境安装脚本..."
|
||||
cat > "$BUILD_DIR/usr/share/config-editor/setup_venv.sh" << 'EOF'
|
||||
#!/bin/bash
|
||||
# 虚拟环境安装脚本
|
||||
# 虚拟环境安装脚本 - 修复sudo环境问题
|
||||
|
||||
set -e
|
||||
|
||||
APP_DIR="/usr/share/config-editor"
|
||||
VENV_DIR="$APP_DIR/venv"
|
||||
@ -104,93 +86,75 @@ if [ "$EUID" -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查虚拟环境是否存在
|
||||
if [ ! -d "$VENV_DIR" ]; then
|
||||
# 清理旧的虚拟环境(如果存在)
|
||||
if [ -d "$VENV_DIR" ]; then
|
||||
echo "清理旧的虚拟环境..."
|
||||
rm -rf "$VENV_DIR"
|
||||
fi
|
||||
|
||||
# 创建虚拟环境
|
||||
echo "创建虚拟环境..."
|
||||
python3 -m venv --system-site-packages "$VENV_DIR"
|
||||
python3 -m venv "$VENV_DIR"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "错误: 无法创建虚拟环境"
|
||||
echo "请确保已安装 python3-venv: sudo apt install python3-venv"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# 激活虚拟环境并安装依赖
|
||||
echo "激活虚拟环境并安装依赖..."
|
||||
source "$VENV_DIR/bin/activate"
|
||||
echo "✓ 虚拟环境创建成功"
|
||||
|
||||
# 修复权限问题
|
||||
echo "修复虚拟环境权限..."
|
||||
chmod -R 755 "$VENV_DIR"
|
||||
chmod +x "$VENV_DIR/bin"/* 2>/dev/null || true
|
||||
chmod +x "$VENV_DIR/bin/python" 2>/dev/null || true
|
||||
chmod +x "$VENV_DIR/bin/pip" 2>/dev/null || true
|
||||
|
||||
# 升级pip
|
||||
echo "升级pip..."
|
||||
python -m pip install --upgrade pip
|
||||
|
||||
# 安装PyQt6
|
||||
# 使用虚拟环境中的pip安装PyQt6 - 关键修复:使用绝对路径
|
||||
echo "安装PyQt6..."
|
||||
pip install PyQt6 -i https://pypi.tuna.tsinghua.edu.cn/simple/
|
||||
|
||||
# 如果有requirements.txt,安装其他依赖
|
||||
if [ -f "$APP_DIR/requirements.txt" ]; then
|
||||
echo "安装其他依赖..."
|
||||
pip install -r "$APP_DIR/requirements.txt" -i https://pypi.tuna.tsinghua.edu.cn/simple/
|
||||
if ! "$VENV_DIR/bin/python" -m pip install PyQt6 2>/dev/null; then
|
||||
echo "尝试使用国内镜像安装..."
|
||||
"$VENV_DIR/bin/python" -m pip install PyQt6 -i https://pypi.tuna.tsinghua.edu.cn/simple/
|
||||
fi
|
||||
|
||||
# 再次确保权限正确
|
||||
echo "设置最终权限..."
|
||||
chmod -R 755 "$VENV_DIR"
|
||||
chmod +x "$VENV_DIR/bin"/* 2>/dev/null || true
|
||||
# 验证安装
|
||||
if ! "$VENV_DIR/bin/python" -c "import PyQt6" 2>/dev/null; then
|
||||
echo "错误: PyQt6安装失败"
|
||||
echo "请尝试手动安装:"
|
||||
echo " sudo $VENV_DIR/bin/pip install PyQt6"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "虚拟环境设置完成"
|
||||
echo "安装在虚拟环境中的包:"
|
||||
pip list
|
||||
echo "✓ PyQt6安装成功"
|
||||
|
||||
# 设置权限
|
||||
chmod -R 755 "$VENV_DIR"
|
||||
|
||||
echo ""
|
||||
echo "虚拟环境设置完成!"
|
||||
echo "虚拟环境位置: $VENV_DIR"
|
||||
echo ""
|
||||
echo "可以测试运行:"
|
||||
echo " $VENV_DIR/bin/python $APP_DIR/config_editor.py"
|
||||
EOF
|
||||
|
||||
chmod +x "$BUILD_DIR/usr/share/config-editor/setup_venv.sh"
|
||||
|
||||
# 创建启动脚本 - 使用虚拟环境(已修复权限检查)
|
||||
# 创建启动脚本
|
||||
echo "创建启动脚本..."
|
||||
cat > "$BUILD_DIR/usr/bin/config-editor" << 'EOF'
|
||||
#!/bin/bash
|
||||
# Config Editor 启动脚本 - 虚拟环境版本
|
||||
# Config Editor 启动脚本
|
||||
|
||||
# 应用目录
|
||||
APP_DIR="/usr/share/config-editor"
|
||||
VENV_DIR="$APP_DIR/venv"
|
||||
LOG_FILE="${HOME}/.config/config-editor/log.txt"
|
||||
|
||||
# 创建日志目录
|
||||
mkdir -p "$(dirname "$LOG_FILE")"
|
||||
# 日志文件
|
||||
LOG_DIR="${HOME}/.config/config-editor"
|
||||
mkdir -p "$LOG_DIR"
|
||||
LOG_FILE="$LOG_DIR/startup.log"
|
||||
|
||||
# 记录启动日志
|
||||
echo "$(date): 启动Config Editor" >> "$LOG_FILE"
|
||||
|
||||
# 设置环境变量
|
||||
export DISPLAY=":${XDG_SESSION_DISPLAY:-1}"
|
||||
export XAUTHORITY="${HOME}/.Xauthority"
|
||||
|
||||
# 尝试多种方法设置DBUS
|
||||
if [ -f "/run/user/$(id -u)/bus" ]; then
|
||||
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus"
|
||||
elif [ -n "$DBUS_SESSION_BUS_ADDRESS" ]; then
|
||||
: # 保持已有设置
|
||||
else
|
||||
# 尝试从进程获取
|
||||
DBUS_ADDR=$(ps -u $(id -u) -o command | grep -o 'dbus-daemon.*address=unix:path=[^ ]*' | head -1 | sed 's/.*address=//')
|
||||
if [ -n "$DBUS_ADDR" ]; then
|
||||
export DBUS_SESSION_BUS_ADDRESS="$DBUS_ADDR"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 修复X11权限
|
||||
if [ -f "${HOME}/.Xauthority" ]; then
|
||||
export XAUTHORITY="${HOME}/.Xauthority"
|
||||
fi
|
||||
# 记录启动信息
|
||||
{
|
||||
echo "========================================"
|
||||
echo "启动时间: $(date)"
|
||||
echo "用户: $(whoami)"
|
||||
echo "DISPLAY: $DISPLAY"
|
||||
} >> "$LOG_FILE"
|
||||
|
||||
# 检查虚拟环境
|
||||
if [ ! -d "$VENV_DIR" ]; then
|
||||
@ -199,29 +163,30 @@ if [ ! -d "$VENV_DIR" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查并修复权限(如果需要)
|
||||
if [ ! -x "$VENV_DIR/bin/python" ] || [ ! -x "$VENV_DIR/bin/pip" ]; then
|
||||
echo "警告: 虚拟环境权限问题,请重新运行安装脚本:"
|
||||
echo " sudo /usr/share/config-editor/setup_venv.sh"
|
||||
# 检查Python可执行文件
|
||||
PYTHON_EXEC="$VENV_DIR/bin/python"
|
||||
if [ ! -x "$PYTHON_EXEC" ]; then
|
||||
PYTHON_EXEC="$VENV_DIR/bin/python3"
|
||||
if [ ! -x "$PYTHON_EXEC" ]; then
|
||||
echo "错误: 虚拟环境中找不到Python可执行文件"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# 检查PyQt6是否安装
|
||||
if ! "$VENV_DIR/bin/python" -c "import PyQt6" 2>/dev/null; then
|
||||
if ! "$PYTHON_EXEC" -c "import PyQt6" 2>/dev/null; then
|
||||
echo "错误: PyQt6未在虚拟环境中安装。请运行:"
|
||||
echo " sudo /usr/share/config-editor/setup_venv.sh"
|
||||
echo "如果仍然失败,请手动安装:"
|
||||
echo " sudo $VENV_DIR/bin/pip install PyQt6"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 切换到应用目录
|
||||
cd "$APP_DIR"
|
||||
|
||||
# 记录环境信息
|
||||
echo "DISPLAY: $DISPLAY" >> "$LOG_FILE"
|
||||
echo "XAUTHORITY: $XAUTHORITY" >> "$LOG_FILE"
|
||||
|
||||
# 使用虚拟环境运行Python应用
|
||||
exec "$VENV_DIR/bin/python" config_editor.py "$@" >> "$LOG_FILE" 2>&1
|
||||
# 启动应用
|
||||
exec "$PYTHON_EXEC" config_editor.py "$@"
|
||||
EOF
|
||||
|
||||
chmod +x "$BUILD_DIR/usr/bin/config-editor"
|
||||
@ -233,12 +198,10 @@ Package: $PACKAGE_NAME
|
||||
Version: $VERSION
|
||||
Architecture: $ARCHITECTURE
|
||||
Depends: python3, python3-venv
|
||||
Recommends: libnotify-bin, x11-xserver-utils
|
||||
Maintainer: $MAINTAINER
|
||||
Description: Configuration Management System (VirtualEnv)
|
||||
A PyQt6-based configuration management editor using virtual environment.
|
||||
Provides grouping management, validation rules, and auto-grouping features.
|
||||
This version uses virtual environment for PyQt6.
|
||||
Description: Config Editor with one-click hide feature
|
||||
A PyQt6-based configuration management editor.
|
||||
Features include one-click hide all configuration items.
|
||||
EOF
|
||||
|
||||
# 创建安装后脚本
|
||||
@ -246,35 +209,23 @@ echo "创建安装后脚本..."
|
||||
cat > "$BUILD_DIR/DEBIAN/postinst" << 'EOF'
|
||||
#!/bin/bash
|
||||
# 安装后脚本
|
||||
set -e
|
||||
|
||||
echo "Config Editor 安装完成!"
|
||||
echo ""
|
||||
echo "更新桌面数据库..."
|
||||
update-desktop-database /usr/share/applications 2>/dev/null || true
|
||||
|
||||
echo ""
|
||||
echo "重要: 需要设置虚拟环境才能运行应用"
|
||||
echo "请执行以下命令完成安装:"
|
||||
echo " sudo /usr/share/config-editor/setup_venv.sh"
|
||||
echo ""
|
||||
echo "使用说明:"
|
||||
echo "1. 设置虚拟环境: sudo /usr/share/config-editor/setup_venv.sh"
|
||||
echo "2. 在终端运行: config-editor"
|
||||
echo "注意: 如果之前安装失败,新版本修复了虚拟环境安装问题"
|
||||
echo " 请确保运行上述命令安装PyQt6到正确的虚拟环境中"
|
||||
|
||||
# 设置文件权限
|
||||
# 更新桌面数据库
|
||||
update-desktop-database /usr/share/applications 2>/dev/null || true
|
||||
|
||||
# 设置权限
|
||||
chmod 755 /usr/bin/config-editor
|
||||
chmod 755 /usr/share/config-editor/setup_venv.sh
|
||||
|
||||
# 设置应用文件权限
|
||||
chmod -R 644 /usr/share/config-editor/* 2>/dev/null || true
|
||||
chmod 755 /usr/share/config-editor/*.py 2>/dev/null || true
|
||||
chmod 755 /usr/share/config-editor/*.sh 2>/dev/null || true
|
||||
|
||||
# 为虚拟环境目录预留权限
|
||||
mkdir -p /usr/share/config-editor/venv 2>/dev/null || true
|
||||
chmod 755 /usr/share/config-editor/venv 2>/dev/null || true
|
||||
|
||||
exit 0
|
||||
EOF
|
||||
|
||||
@ -285,7 +236,6 @@ echo "构建deb包..."
|
||||
dpkg-deb --build "$BUILD_DIR" "${PACKAGE_NAME}_${VERSION}_${ARCHITECTURE}.deb"
|
||||
|
||||
# 验证包
|
||||
echo "验证deb包..."
|
||||
if dpkg -I "${PACKAGE_NAME}_${VERSION}_${ARCHITECTURE}.deb" > /dev/null; then
|
||||
echo "✓ 包验证成功"
|
||||
else
|
||||
@ -293,28 +243,18 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 清理构建目录
|
||||
echo "清理构建目录..."
|
||||
# 清理
|
||||
rm -rf "$BUILD_DIR"
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "构建成功完成!"
|
||||
echo "构建完成!"
|
||||
echo "生成的deb包: ${PACKAGE_NAME}_${VERSION}_${ARCHITECTURE}.deb"
|
||||
echo ""
|
||||
echo "安装步骤:"
|
||||
echo "1. 安装deb包: sudo dpkg -i ${PACKAGE_NAME}_${VERSION}_${ARCHITECTURE}.deb"
|
||||
echo "2. 安装依赖(如有需要): sudo apt install -f"
|
||||
echo "3. 设置虚拟环境: sudo /usr/share/config-editor/setup_venv.sh"
|
||||
echo "1. 卸载旧版本: sudo dpkg -r config-editor"
|
||||
echo "2. 安装新版本: sudo dpkg -i ${PACKAGE_NAME}_${VERSION}_${ARCHITECTURE}.deb"
|
||||
echo "3. 修复虚拟环境: sudo /usr/share/config-editor/setup_venv.sh"
|
||||
echo ""
|
||||
echo "此版本特点:"
|
||||
echo "✓ 修复了虚拟环境权限问题"
|
||||
echo "✓ 使用 --system-site-packages 参数"
|
||||
echo "✓ 自动使用清华PyPI镜像"
|
||||
echo "✓ 简化了依赖和脚本"
|
||||
echo "重要: 新版本修复了虚拟环境安装问题"
|
||||
echo "=========================================="
|
||||
|
||||
# 显示包信息
|
||||
echo ""
|
||||
echo "包信息:"
|
||||
dpkg -I "${PACKAGE_NAME}_${VERSION}_${ARCHITECTURE}.deb"
|
||||
|
||||
167
config_editor.py
167
config_editor.py
@ -262,6 +262,24 @@ class ConfigManagementWindow(QDialog):
|
||||
group_layout.addLayout(group_btn_layout)
|
||||
right_layout.addWidget(group_group)
|
||||
|
||||
# 批量操作
|
||||
batch_group = QGroupBox("批量操作")
|
||||
batch_layout = QVBoxLayout(batch_group)
|
||||
batch_layout.setContentsMargins(8, 8, 8, 8)
|
||||
|
||||
batch_btn_layout = QHBoxLayout()
|
||||
self.show_all_btn = QPushButton("全部显示")
|
||||
self.show_all_btn.clicked.connect(self.show_all_fields)
|
||||
self.hide_all_btn = QPushButton("全部隐藏")
|
||||
self.hide_all_btn.clicked.connect(self.hide_all_fields)
|
||||
|
||||
batch_btn_layout.addWidget(self.show_all_btn)
|
||||
batch_btn_layout.addWidget(self.hide_all_btn)
|
||||
batch_btn_layout.addStretch()
|
||||
|
||||
batch_layout.addLayout(batch_btn_layout)
|
||||
right_layout.addWidget(batch_group)
|
||||
|
||||
right_layout.addStretch()
|
||||
splitter.addWidget(right_widget)
|
||||
|
||||
@ -292,11 +310,15 @@ class ConfigManagementWindow(QDialog):
|
||||
|
||||
self.update_fields_count()
|
||||
|
||||
# 加载分组
|
||||
self.category_combo.clear()
|
||||
categories = list(self.rules.get("categories", {}).keys())
|
||||
# 确保"未分类"分组始终存在
|
||||
if "未分类" not in categories:
|
||||
categories.append("未分类")
|
||||
if categories:
|
||||
for category in sorted(categories):
|
||||
self.category_combo.addItem(category)
|
||||
self.category_combo.addItem("未分类")
|
||||
|
||||
def filter_fields(self, search_text):
|
||||
"""根据搜索文本过滤配置项列表"""
|
||||
@ -364,12 +386,14 @@ class ConfigManagementWindow(QDialog):
|
||||
display_name = self.rules.get("display_names", {}).get(field_name, field_name)
|
||||
self.display_name_edit.setText(display_name)
|
||||
|
||||
# 查找配置项所属的分组
|
||||
category = "未分类"
|
||||
for cat, fields in self.rules.get("categories", {}).items():
|
||||
if field_name in fields:
|
||||
category = cat
|
||||
break
|
||||
|
||||
# 设置分组
|
||||
index = self.category_combo.findText(category)
|
||||
if index >= 0:
|
||||
self.category_combo.setCurrentIndex(index)
|
||||
@ -416,12 +440,25 @@ class ConfigManagementWindow(QDialog):
|
||||
|
||||
# 更新分组
|
||||
category = self.category_combo.currentText().strip()
|
||||
if category and category != "未分类":
|
||||
# 从旧分组移除
|
||||
for cat, fields in self.rules.get("categories", {}).items():
|
||||
if category == "未分类":
|
||||
# 从所有分组中移除该字段
|
||||
for cat, fields in self.rules.setdefault("categories", {}).items():
|
||||
if cat != "未分类" and field_name in fields:
|
||||
fields.remove(field_name)
|
||||
# 确保在"未分类"分组中
|
||||
if "未分类" not in self.rules["categories"]:
|
||||
self.rules["categories"]["未分类"] = []
|
||||
if field_name not in self.rules["categories"]["未分类"]:
|
||||
self.rules["categories"]["未分类"].append(field_name)
|
||||
elif category: # 其他分组
|
||||
# 从所有分组中移除该字段
|
||||
for cat, fields in self.rules.setdefault("categories", {}).items():
|
||||
if field_name in fields:
|
||||
fields.remove(field_name)
|
||||
break
|
||||
|
||||
# 确保"未分类"分组存在
|
||||
if "未分类" not in self.rules["categories"]:
|
||||
self.rules["categories"]["未分类"] = []
|
||||
|
||||
# 添加到新分组
|
||||
if category not in self.rules["categories"]:
|
||||
@ -503,11 +540,62 @@ class ConfigManagementWindow(QDialog):
|
||||
current_group = self.category_combo.currentText()
|
||||
if current_group and current_group != "未分类":
|
||||
reply = QMessageBox.question(self, "确认删除",
|
||||
f"确定要删除分组 '{current_group}' 吗?")
|
||||
f"确定要删除分组 '{current_group}' 吗?\n该分组中的所有配置项将被移到'未分类'分组。")
|
||||
if reply == QMessageBox.StandardButton.Yes:
|
||||
if current_group in self.rules.get("categories", {}):
|
||||
# 将该分组中的配置项移到"未分类"分组
|
||||
fields_to_move = self.rules["categories"][current_group]
|
||||
if "未分类" not in self.rules["categories"]:
|
||||
self.rules["categories"]["未分类"] = []
|
||||
|
||||
for field_name in fields_to_move:
|
||||
if field_name not in self.rules["categories"]["未分类"]:
|
||||
self.rules["categories"]["未分类"].append(field_name)
|
||||
|
||||
# 删除分组
|
||||
del self.rules["categories"][current_group]
|
||||
self.category_combo.removeItem(self.category_combo.findText(current_group))
|
||||
|
||||
# 从下拉框中移除
|
||||
index = self.category_combo.findText(current_group)
|
||||
if index >= 0:
|
||||
self.category_combo.removeItem(index)
|
||||
# 设置当前选中的分组为"未分类"
|
||||
self.category_combo.setCurrentText("未分类")
|
||||
|
||||
def show_all_fields(self):
|
||||
"""批量显示所有配置项(取消所有隐藏)"""
|
||||
reply = QMessageBox.question(self, "确认",
|
||||
"确定要取消所有配置项的隐藏状态吗?",
|
||||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
|
||||
if reply == QMessageBox.StandardButton.Yes:
|
||||
# 清空隐藏列表
|
||||
self.rules["hidden"] = []
|
||||
|
||||
# 更新当前选中字段的隐藏状态
|
||||
current_item = self.fields_list.currentItem()
|
||||
if current_item:
|
||||
self.hidden_checkbox.setChecked(False)
|
||||
|
||||
QMessageBox.information(self, "完成", "已取消所有配置项的隐藏状态")
|
||||
|
||||
def hide_all_fields(self):
|
||||
"""批量隐藏所有配置项"""
|
||||
reply = QMessageBox.question(self, "确认",
|
||||
"确定要隐藏所有配置项吗?",
|
||||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
|
||||
if reply == QMessageBox.StandardButton.Yes:
|
||||
# 获取所有配置项的名称
|
||||
all_fields = list(self.config_fields.keys())
|
||||
|
||||
# 将所有配置项添加到隐藏列表
|
||||
self.rules["hidden"] = all_fields
|
||||
|
||||
# 更新当前选中字段的隐藏状态
|
||||
current_item = self.fields_list.currentItem()
|
||||
if current_item:
|
||||
self.hidden_checkbox.setChecked(True)
|
||||
|
||||
QMessageBox.information(self, "完成", "已隐藏所有配置项")
|
||||
|
||||
def get_updated_rules(self):
|
||||
"""获取更新后的规则"""
|
||||
@ -789,6 +877,12 @@ class ConfigEditor(QMainWindow):
|
||||
self.toggle_hidden_btn.toggled.connect(self.toggle_hidden_fields)
|
||||
button_layout.addWidget(self.toggle_hidden_btn)
|
||||
|
||||
# 新增:一键隐藏所有配置项按钮
|
||||
self.hide_all_btn = QPushButton("一键隐藏所有项")
|
||||
self.hide_all_btn.clicked.connect(self.hide_all_fields)
|
||||
self.hide_all_btn.setStyleSheet("QPushButton { background-color: #ff9800; color: white; }")
|
||||
button_layout.addWidget(self.hide_all_btn)
|
||||
|
||||
main_layout.addLayout(button_layout)
|
||||
|
||||
# 更新路径显示
|
||||
@ -878,6 +972,7 @@ class ConfigEditor(QMainWindow):
|
||||
self.load_config()
|
||||
|
||||
def init_category_tabs(self):
|
||||
"""初始化分类标签页"""
|
||||
self.category_widgets.clear()
|
||||
categories = list(self.rules.get("categories", {}).keys())
|
||||
if not categories:
|
||||
@ -887,6 +982,7 @@ class ConfigEditor(QMainWindow):
|
||||
self.create_category_tab(category)
|
||||
|
||||
def create_category_tab(self, category):
|
||||
"""创建分类标签页"""
|
||||
tab = QWidget()
|
||||
layout = QVBoxLayout(tab)
|
||||
layout.setContentsMargins(4, 4, 4, 4)
|
||||
@ -908,17 +1004,24 @@ class ConfigEditor(QMainWindow):
|
||||
self.tab_widget.addTab(tab, category)
|
||||
|
||||
def load_rules(self):
|
||||
"""加载规则文件"""
|
||||
try:
|
||||
if os.path.exists(self.rules_file):
|
||||
with open(self.rules_file, 'r', encoding='utf-8') as f:
|
||||
self.rules = json.load(f)
|
||||
|
||||
# 确保规则中有"未分类"分组
|
||||
if "categories" not in self.rules:
|
||||
self.rules["categories"] = {}
|
||||
if "未分类" not in self.rules["categories"]:
|
||||
self.rules["categories"]["未分类"] = []
|
||||
|
||||
# 确保规则中有field_decimals字段
|
||||
if "field_decimals" not in self.rules:
|
||||
self.rules["field_decimals"] = {}
|
||||
else:
|
||||
self.rules = {
|
||||
"categories": {},
|
||||
"categories": {"未分类": []}, # 保留"未分类"分组
|
||||
"display_names": {},
|
||||
"tooltips": {},
|
||||
"field_types": {},
|
||||
@ -934,7 +1037,7 @@ class ConfigEditor(QMainWindow):
|
||||
except Exception as e:
|
||||
print(f"加载规则文件失败: {e}")
|
||||
self.rules = {
|
||||
"categories": {},
|
||||
"categories": {"未分类": []},
|
||||
"display_names": {},
|
||||
"tooltips": {},
|
||||
"field_types": {},
|
||||
@ -944,6 +1047,7 @@ class ConfigEditor(QMainWindow):
|
||||
}
|
||||
|
||||
def save_rules(self):
|
||||
"""保存规则文件"""
|
||||
try:
|
||||
with open(self.rules_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(self.rules, f, indent=2, ensure_ascii=False)
|
||||
@ -951,18 +1055,22 @@ class ConfigEditor(QMainWindow):
|
||||
print(f"保存规则文件失败: {e}")
|
||||
|
||||
def categorize_field(self, field_name):
|
||||
"""为字段分类,如果未分配分组则归到'未分类'"""
|
||||
for category, fields in self.rules.get("categories", {}).items():
|
||||
if field_name in fields:
|
||||
return category
|
||||
return "未分类"
|
||||
return "未分类" # 默认归到"未分类"
|
||||
|
||||
def get_display_name(self, field_name):
|
||||
"""获取字段的显示名称"""
|
||||
return self.rules.get("display_names", {}).get(field_name, field_name)
|
||||
|
||||
def get_tooltip(self, field_name):
|
||||
"""获取字段的提示信息"""
|
||||
return self.rules.get("tooltips", {}).get(field_name, f"配置项: {field_name}")
|
||||
|
||||
def get_field_type(self, field_name, value):
|
||||
"""获取字段类型"""
|
||||
if field_name in self.rules.get("field_types", {}):
|
||||
return self.rules["field_types"][field_name]
|
||||
|
||||
@ -1055,7 +1163,7 @@ class ConfigEditor(QMainWindow):
|
||||
all_config_fields[var_name] = ConfigField(
|
||||
name=var_name,
|
||||
value=var_value,
|
||||
category=self.categorize_field(var_name),
|
||||
category=self.categorize_field(var_name), # 使用分类方法
|
||||
display_name=self.get_display_name(var_name),
|
||||
field_type=field_type,
|
||||
decimals=decimals,
|
||||
@ -1075,7 +1183,7 @@ class ConfigEditor(QMainWindow):
|
||||
all_config_fields[var_name] = ConfigField(
|
||||
name=var_name,
|
||||
value=value_str,
|
||||
category=self.categorize_field(var_name),
|
||||
category=self.categorize_field(var_name), # 使用分类方法
|
||||
display_name=self.get_display_name(var_name),
|
||||
field_type="str",
|
||||
decimals=None,
|
||||
@ -1091,7 +1199,7 @@ class ConfigEditor(QMainWindow):
|
||||
all_config_fields[var_name] = ConfigField(
|
||||
name=var_name,
|
||||
value="无法解析的值",
|
||||
category=self.categorize_field(var_name),
|
||||
category=self.categorize_field(var_name), # 使用分类方法
|
||||
display_name=self.get_display_name(var_name),
|
||||
field_type="str",
|
||||
decimals=None,
|
||||
@ -1109,6 +1217,7 @@ class ConfigEditor(QMainWindow):
|
||||
return {}, {}, ""
|
||||
|
||||
def create_field_widget(self, config_field):
|
||||
"""创建字段编辑控件"""
|
||||
field_type = config_field.get_actual_field_type()
|
||||
|
||||
if field_type == "bool":
|
||||
@ -1315,7 +1424,7 @@ class ConfigEditor(QMainWindow):
|
||||
fields.sort(key=lambda x: x.name)
|
||||
|
||||
# 使用GroupBox,更清晰的分组
|
||||
group_box = QGroupBox(f"{category}配置项")
|
||||
group_box = QGroupBox(f"{category}")
|
||||
group_layout = QVBoxLayout(group_box)
|
||||
group_layout.setSpacing(6)
|
||||
|
||||
@ -1328,6 +1437,7 @@ class ConfigEditor(QMainWindow):
|
||||
layout.addWidget(group_box)
|
||||
|
||||
def load_config(self):
|
||||
"""加载配置文件"""
|
||||
try:
|
||||
# 检查配置文件是否存在
|
||||
if not self.check_config_file():
|
||||
@ -1351,7 +1461,7 @@ class ConfigEditor(QMainWindow):
|
||||
self.generate_dynamic_ui(show_hidden)
|
||||
|
||||
hidden_count = len(self.all_config_fields) - len(self.config_fields)
|
||||
self.statusBar().showMessage(f"成功加载 {len(self.config_fields)} 个配置项 ({hidden_count} 个已隐藏)")
|
||||
self.statusBar().showMessage(f"成功加载 {len(self.config_data)} 个配置项 ({len(self.config_fields)} 个显示, {hidden_count} 个隐藏)")
|
||||
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "错误", f"加载配置文件失败:{str(e)}")
|
||||
@ -1370,7 +1480,34 @@ class ConfigEditor(QMainWindow):
|
||||
self.toggle_hidden_btn.setText("显示隐藏项")
|
||||
self.statusBar().showMessage("已隐藏标记为隐藏的配置项")
|
||||
|
||||
def hide_all_fields(self):
|
||||
"""一键隐藏所有配置项"""
|
||||
reply = QMessageBox.question(
|
||||
self, "确认一键隐藏",
|
||||
"确定要隐藏所有配置项吗?\n隐藏后,页面上将不显示任何配置项。\n如需显示,需要在规则管理中取消隐藏。",
|
||||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
||||
)
|
||||
|
||||
if reply == QMessageBox.StandardButton.Yes:
|
||||
# 获取所有配置项的名称
|
||||
all_field_names = list(self.all_config_fields.keys())
|
||||
|
||||
# 将所有配置项添加到隐藏列表
|
||||
self.rules["hidden"] = all_field_names
|
||||
|
||||
# 保存规则
|
||||
self.save_rules()
|
||||
|
||||
# 重新加载配置
|
||||
self.load_config()
|
||||
|
||||
# 更新状态栏
|
||||
self.statusBar().showMessage("已隐藏所有配置项,页面已清空")
|
||||
|
||||
QMessageBox.information(self, "完成", "已成功隐藏所有配置项。\n如需显示配置项,请在规则管理中取消隐藏。")
|
||||
|
||||
def manage_rules(self):
|
||||
"""管理规则"""
|
||||
dialog = ConfigManagementWindow(self.rules, self.all_config_fields, self)
|
||||
if dialog.exec() == QDialog.DialogCode.Accepted:
|
||||
updated_rules = dialog.get_updated_rules()
|
||||
|
||||
@ -1,131 +1,11 @@
|
||||
{
|
||||
"categories": {
|
||||
"数据库配置": [
|
||||
"CONNECTION",
|
||||
"REDIS_ADDRESS",
|
||||
"REDIS_PORT",
|
||||
"SYNC_INTERVAL",
|
||||
"REDIS_FIELD_MAPPING"
|
||||
],
|
||||
"PLC控制": [
|
||||
"PLC_ADDRESS",
|
||||
"PLC_PORT",
|
||||
"NH3_LOWER",
|
||||
"NH3_UPPER",
|
||||
"IS_AUTO",
|
||||
"AI_NH3_ADDRESS",
|
||||
"FLOW_FEEDBACK_ADDRESS",
|
||||
"NH3_MANUAL"
|
||||
],
|
||||
"训练参数": [
|
||||
"RESAMPLE_SIZE",
|
||||
"MISSING_VALUE_LENGTH",
|
||||
"MEAN_MASE",
|
||||
"INTERVAL_SIZE_V2",
|
||||
"LAGS",
|
||||
"PREDICT_FH_V2",
|
||||
"TRAIN_DAYS_V2",
|
||||
"THREAD_COUNT",
|
||||
"GPU_RAM_PART",
|
||||
"CNF_PREDICT_NUMBER",
|
||||
"CNF_LAGS",
|
||||
"CNF_LAGS_PC",
|
||||
"CNF_OUTPUT_CHUNK_LENGTH",
|
||||
"CNF_THREAD_COUNT",
|
||||
"CNF_ALARM_LEVEL_1",
|
||||
"CNF_ALARM_LEVEL_2",
|
||||
"CNF_ALARM_LEVEL_3"
|
||||
],
|
||||
"计算参数": [
|
||||
"NH3_LOWER",
|
||||
"NH3_UPPER",
|
||||
"SMOKE_VOLUME",
|
||||
"SMOKE_VOLUME_UPPER",
|
||||
"SMOKE_VOLUME_LOWER",
|
||||
"CONC",
|
||||
"DENSITY",
|
||||
"IS_SOLUTION",
|
||||
"DECLINE_LIMIT",
|
||||
"LOWER_LIMIT_DURATION",
|
||||
"RAISE_LIMIT",
|
||||
"UPPER_LIMIT_DURATION",
|
||||
"PAS_TARGET",
|
||||
"ACTUAL_PAS_TARGET_DIFF_CEMS",
|
||||
"ACTUAL_PAS_TARGET_DIFF_PW",
|
||||
"ACTUAL_PAS_TARGET_CEMS",
|
||||
"ACTUAL_PAS_TARGET_PW",
|
||||
"DYNAMIC_TARGET_UPPER",
|
||||
"DYNAMIC_TARGET_LOWER",
|
||||
"DYNAMIC_TARGET_START_MINUTE",
|
||||
"DYNAMIC_TARGET_END_MINUTE",
|
||||
"NH3_MANUAL"
|
||||
],
|
||||
"控制修正": [
|
||||
"OUT_NH3_TARGET",
|
||||
"OUT_NH3_TARGET_LOWER",
|
||||
"OUT_NH3_TARGET_UPPER",
|
||||
"CORR_PER_LIMIT",
|
||||
"CORR_SLOPE",
|
||||
"AVG_PRIMARY_ADJUST_TIME",
|
||||
"PRIMARY_ADJUST_THRESHOLD",
|
||||
"PRIMARY_ADJUST_INC_MULT",
|
||||
"PRIMARY_ADJUST_DEC_MULT",
|
||||
"CONTROL_METHOD_THRESHOLD",
|
||||
"AVG_CORR_NOX_THRESHOLD",
|
||||
"AVG_SMOKE_ADJUST_TIME",
|
||||
"PRIMARY_ADJUST_SWITCH",
|
||||
"SECONDARY_ADJUST_SWITCH",
|
||||
"AVG_PRED_NOX_ADJUST_TIME",
|
||||
"ADVANCE_TIME",
|
||||
"BLOWBACK_TIME",
|
||||
"EFFICIENCY",
|
||||
"EFFICIENCY_ADJUST_INTERVAL",
|
||||
"EFFICIENCY_ADJUST_ADVANCE_TIME",
|
||||
"AVG_EFFICIENCY_ADJUST_TIME",
|
||||
"EFFICIENCY_ADJUST_THRESHOLD",
|
||||
"EFFICIENCY_ADJUST_UPPER",
|
||||
"EFFICIENCY_ADJUST_LOWER",
|
||||
"CORR_SLOPE_2",
|
||||
"OUT_NH3_ADJUST_SWITCH",
|
||||
"OUT_NH3_ADJUST_THRESHOLD",
|
||||
"OUT_NH3_ADJUST_PCT"
|
||||
],
|
||||
"PID控制": [
|
||||
"PID_VALVE_IS_AUTO",
|
||||
"PID_VALVE_LOWER",
|
||||
"PID_VALVE_UPPER",
|
||||
"PID_VALVE_MANUAL",
|
||||
"PID_VALVE_AUTO_ADDRESS",
|
||||
"PID_VALVE_READ_ADDRESS",
|
||||
"PID_VALVE_MANUAL_ADDRESS",
|
||||
"PID_VALVE_FEEDBACK_ADDRESS"
|
||||
],
|
||||
"MQTT配置": [
|
||||
"MQTT_HOST",
|
||||
"MQTT_PORT",
|
||||
"MQTT_USERNAME",
|
||||
"MQTT_PASSWORD",
|
||||
"MQTT_TOPIC",
|
||||
"MQTT_CLIENT_ID"
|
||||
],
|
||||
"其他配置": [
|
||||
"VALVE_UPPER",
|
||||
"VALVE_LOWER",
|
||||
"MODEL_CHANNEL",
|
||||
"CLEAN_UPPER",
|
||||
"CLEAN_LOWER",
|
||||
"ALARM_WEBHOOK",
|
||||
"ABS_DIFF_THRESHOLD"
|
||||
],
|
||||
"未分类": [
|
||||
"EMERGENCY_ADJUST_INC_MULT",
|
||||
"USED_RAM_LIMIT"
|
||||
]
|
||||
},
|
||||
"display_names": {
|
||||
"ABS_DIFF_THRESHOLD": "两个出口NOx绝对值误差阈值"
|
||||
"未分类": []
|
||||
},
|
||||
"display_names": {},
|
||||
"tooltips": {},
|
||||
"field_types": {},
|
||||
"hidden": []
|
||||
"field_decimals": {},
|
||||
"hidden": [],
|
||||
"validations": {}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user