diff --git a/build.sh b/build.sh index b5f725c..8e52510 100644 --- a/build.sh +++ b/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 " 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 + cp config_editor_settings.json "$BUILD_DIR/usr/share/config-editor/" 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 - echo "创建虚拟环境..." - python3 -m venv --system-site-packages "$VENV_DIR" - - if [ $? -ne 0 ]; then - echo "错误: 无法创建虚拟环境" - echo "请确保已安装 python3-venv: sudo apt install python3-venv" - exit 1 - fi +# 清理旧的虚拟环境(如果存在) +if [ -d "$VENV_DIR" ]; then + echo "清理旧的虚拟环境..." + rm -rf "$VENV_DIR" fi -# 激活虚拟环境并安装依赖 -echo "激活虚拟环境并安装依赖..." -source "$VENV_DIR/bin/activate" +# 创建虚拟环境 +echo "创建虚拟环境..." +python3 -m venv "$VENV_DIR" -# 修复权限问题 -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 +if [ $? -ne 0 ]; then + echo "错误: 无法创建虚拟环境" + echo "请确保已安装 python3-venv: sudo apt install python3-venv" + exit 1 +fi -# 升级pip -echo "升级pip..." -python -m pip install --upgrade pip +echo "✓ 虚拟环境创建成功" -# 安装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" - exit 1 +# 检查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" diff --git a/config_editor.py b/config_editor.py index 5f6f953..2673184 100644 --- a/config_editor.py +++ b/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()) - for category in sorted(categories): - self.category_combo.addItem(category) - self.category_combo.addItem("未分类") + # 确保"未分类"分组始终存在 + if "未分类" not in categories: + categories.append("未分类") + if categories: + for category in sorted(categories): + self.category_combo.addItem(category) 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() diff --git a/config_editor_rules.json b/config_editor_rules.json index f3dfa9f..65bd66a 100644 --- a/config_editor_rules.json +++ b/config_editor_rules.json @@ -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绝对值误差阈值" - }, - "tooltips": {}, - "field_types": {}, - "hidden": [] -} \ No newline at end of file +{ + "categories": { + "未分类": [] + }, + "display_names": {}, + "tooltips": {}, + "field_types": {}, + "field_decimals": {}, + "hidden": [], + "validations": {} +}