Update
This commit is contained in:
13
config/__init__.py
Normal file
13
config/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Config Module
|
||||
-------------
|
||||
配置管理相关模块
|
||||
"""
|
||||
|
||||
from .config_manager import ConfigManager
|
||||
from .icon_config import IconConfigManager
|
||||
from . import constants
|
||||
|
||||
__all__ = ['ConfigManager', 'IconConfigManager', 'constants']
|
||||
623
config/config_manager.py
Normal file
623
config/config_manager.py
Normal file
@@ -0,0 +1,623 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
配置管理模块 - 负责读取和保存应用配置
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from typing import Dict, List, Optional
|
||||
from .icon_config import IconConfigManager
|
||||
from .constants import DEFAULT_TASK_FOLDER_TEMPLATES
|
||||
|
||||
|
||||
class ConfigManager:
|
||||
"""管理NexusLauncher的配置文件"""
|
||||
|
||||
def __init__(self, config_file: str = "config.json"):
|
||||
self.config_file = config_file
|
||||
self.config_data = self._load_config()
|
||||
|
||||
# 如果配置文件不存在,保存默认配置
|
||||
if not os.path.exists(self.config_file):
|
||||
print("[INFO] Config file not found, creating default config.json")
|
||||
self.save_config()
|
||||
|
||||
# 创建图标配置管理器
|
||||
self.icon_config = IconConfigManager(self.config_data, self._get_icons_dir)
|
||||
|
||||
def _get_icons_dir(self) -> str:
|
||||
"""获取 icons 目录路径(避免循环导入)"""
|
||||
if getattr(sys, 'frozen', False):
|
||||
# 打包后的应用
|
||||
return os.path.join(sys._MEIPASS, "icons")
|
||||
else:
|
||||
# 开发环境
|
||||
config_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
project_root = os.path.dirname(config_dir)
|
||||
return os.path.join(project_root, "icons")
|
||||
|
||||
def _load_config(self) -> Dict:
|
||||
"""加载配置文件"""
|
||||
if os.path.exists(self.config_file):
|
||||
try:
|
||||
with open(self.config_file, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
print(f"Failed to load configuration file: {e}")
|
||||
return self._get_default_config()
|
||||
else:
|
||||
return self._get_default_config()
|
||||
|
||||
def _get_default_config(self) -> Dict:
|
||||
"""获取默认配置"""
|
||||
return {
|
||||
"projects": {
|
||||
"Project_01": {
|
||||
"icon": "NexusLauncher.ico", # 默认项目图标
|
||||
"color": "", # 项目背景颜色
|
||||
"apps": []
|
||||
}
|
||||
},
|
||||
"current_project": "Project_01",
|
||||
"window_size": {
|
||||
"width": 425,
|
||||
"height": 480
|
||||
},
|
||||
"icon_size": 80, # 图标大小,默认80x80
|
||||
"app_icons": {}, # 应用图标映射,格式:{"app_path": "icon_path"}
|
||||
"app_colors": {}, # 应用按钮颜色映射,格式:{"app_path": "#RRGGBB"}
|
||||
"task_folder_templates": self._get_default_task_templates(), # 任务类型默认文件夹结构
|
||||
"task_settings": {} # 已废弃:旧的任务设置存储位置,现在存储在 projects.项目名.task_settings
|
||||
}
|
||||
|
||||
def save_config(self) -> bool:
|
||||
"""保存配置到文件"""
|
||||
try:
|
||||
# 重新排序项目字段:icon, color, apps, task_settings
|
||||
if "projects" in self.config_data:
|
||||
for project_name, project_data in self.config_data["projects"].items():
|
||||
ordered_project = {}
|
||||
# 按顺序添加字段
|
||||
if "icon" in project_data:
|
||||
ordered_project["icon"] = project_data["icon"]
|
||||
if "color" in project_data:
|
||||
ordered_project["color"] = project_data["color"]
|
||||
if "apps" in project_data:
|
||||
ordered_project["apps"] = project_data["apps"]
|
||||
if "task_settings" in project_data:
|
||||
ordered_project["task_settings"] = project_data["task_settings"]
|
||||
|
||||
# 替换原有项目数据
|
||||
self.config_data["projects"][project_name] = ordered_project
|
||||
|
||||
with open(self.config_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(self.config_data, f, ensure_ascii=False, indent=4)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Failed to save configuration file: {e}")
|
||||
return False
|
||||
|
||||
def reload_config(self) -> bool:
|
||||
"""重新加载配置文件
|
||||
|
||||
Returns:
|
||||
是否加载成功
|
||||
"""
|
||||
try:
|
||||
self.config_data = self._load_config()
|
||||
# 重新创建图标配置管理器以使用新的config_data引用
|
||||
self.icon_config = IconConfigManager(self.config_data, self._get_icons_dir)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Failed to reload config file: {e}")
|
||||
return False
|
||||
|
||||
def get_projects(self) -> List[str]:
|
||||
"""获取所有项目名称"""
|
||||
return list(self.config_data.get("projects", {}).keys())
|
||||
|
||||
def get_current_project(self) -> str:
|
||||
"""获取当前选中的项目"""
|
||||
return self.config_data.get("current_project", "")
|
||||
|
||||
def set_current_project(self, project_name: str):
|
||||
"""设置当前项目"""
|
||||
if project_name in self.config_data.get("projects", {}):
|
||||
self.config_data["current_project"] = project_name
|
||||
self.save_config()
|
||||
|
||||
def get_apps(self, project_name: Optional[str] = None) -> List[Dict]:
|
||||
"""获取指定项目的应用列表"""
|
||||
if project_name is None:
|
||||
project_name = self.get_current_project()
|
||||
|
||||
projects = self.config_data.get("projects", {})
|
||||
if project_name in projects:
|
||||
return projects[project_name].get("apps", [])
|
||||
return []
|
||||
|
||||
def add_project(self, project_name: str, default_icon: str = None) -> bool:
|
||||
"""添加新项目
|
||||
|
||||
Args:
|
||||
project_name: 项目名称
|
||||
default_icon: 默认图标路径(可选)
|
||||
"""
|
||||
if "projects" not in self.config_data:
|
||||
self.config_data["projects"] = {}
|
||||
|
||||
if project_name in self.config_data["projects"]:
|
||||
return False
|
||||
|
||||
self.config_data["projects"][project_name] = {
|
||||
"icon": default_icon if default_icon else "",
|
||||
"color": "",
|
||||
"apps": []
|
||||
}
|
||||
return self.save_config()
|
||||
|
||||
def delete_project(self, project_name: str) -> bool:
|
||||
"""删除项目"""
|
||||
if project_name in self.config_data.get("projects", {}):
|
||||
# 删除项目配置(包含图标和颜色)
|
||||
del self.config_data["projects"][project_name]
|
||||
|
||||
# 如果删除的是当前项目,切换到第一个项目
|
||||
if self.config_data.get("current_project") == project_name:
|
||||
projects = self.get_projects()
|
||||
if projects:
|
||||
self.config_data["current_project"] = projects[0]
|
||||
else:
|
||||
self.config_data["current_project"] = ""
|
||||
|
||||
return self.save_config()
|
||||
return False
|
||||
|
||||
def rename_project(self, old_name: str, new_name: str) -> bool:
|
||||
"""重命名项目"""
|
||||
# 检查旧项目是否存在
|
||||
if old_name not in self.config_data.get("projects", {}):
|
||||
return False
|
||||
|
||||
# 检查新名称是否已存在
|
||||
if new_name in self.config_data.get("projects", {}):
|
||||
return False
|
||||
|
||||
# 重命名项目
|
||||
self.config_data["projects"][new_name] = self.config_data["projects"].pop(old_name)
|
||||
|
||||
# 如果重命名的是当前项目,更新当前项目名称
|
||||
if self.config_data.get("current_project") == old_name:
|
||||
self.config_data["current_project"] = new_name
|
||||
|
||||
return self.save_config()
|
||||
|
||||
def add_app(self, project_name: str, app_name: str, app_path: str, version: str) -> bool:
|
||||
"""添加应用到指定项目"""
|
||||
if project_name not in self.config_data.get("projects", {}):
|
||||
return False
|
||||
|
||||
app_data = {
|
||||
"name": app_name,
|
||||
"path": app_path,
|
||||
"version": version
|
||||
}
|
||||
|
||||
self.config_data["projects"][project_name]["apps"].append(app_data)
|
||||
return self.save_config()
|
||||
|
||||
def update_app(self, project_name: str, app_index: int, app_name: str, app_path: str, version: str) -> bool:
|
||||
"""更新应用信息"""
|
||||
if project_name not in self.config_data.get("projects", {}):
|
||||
return False
|
||||
|
||||
apps = self.config_data["projects"][project_name]["apps"]
|
||||
if 0 <= app_index < len(apps):
|
||||
apps[app_index] = {
|
||||
"name": app_name,
|
||||
"path": app_path,
|
||||
"version": version
|
||||
}
|
||||
return self.save_config()
|
||||
return False
|
||||
|
||||
def delete_app(self, project_name: str, app_index: int) -> bool:
|
||||
"""删除应用"""
|
||||
if project_name not in self.config_data.get("projects", {}):
|
||||
return False
|
||||
|
||||
apps = self.config_data["projects"][project_name]["apps"]
|
||||
if 0 <= app_index < len(apps):
|
||||
apps.pop(app_index)
|
||||
return self.save_config()
|
||||
return False
|
||||
|
||||
def reorder_apps(self, project_name: str, from_index: int, to_index: int) -> bool:
|
||||
"""重新排序应用,支持拖到列表末尾"""
|
||||
if project_name not in self.config_data.get("projects", {}):
|
||||
return False
|
||||
|
||||
apps = self.config_data["projects"][project_name]["apps"]
|
||||
app_count = len(apps)
|
||||
# 允许目标索引等于列表长度(表示插入到末尾)
|
||||
if not (0 <= from_index < app_count and 0 <= to_index <= app_count):
|
||||
return False
|
||||
|
||||
app = apps.pop(from_index)
|
||||
# 如果从上方拖到下方,移除后目标索引需要左移一位
|
||||
if from_index < to_index:
|
||||
to_index -= 1
|
||||
# 再次夹紧,防止越界
|
||||
to_index = max(0, min(to_index, len(apps)))
|
||||
apps.insert(to_index, app)
|
||||
return self.save_config()
|
||||
|
||||
def get_window_size(self) -> tuple:
|
||||
"""获取窗口大小"""
|
||||
size = self.config_data.get("window_size", {"width": 400, "height": 400})
|
||||
return (size.get("width", 400), size.get("height", 400))
|
||||
|
||||
def save_window_size(self, width: int, height: int):
|
||||
"""保存窗口大小"""
|
||||
self.config_data["window_size"] = {"width": width, "height": height}
|
||||
self.save_config()
|
||||
|
||||
def get_app_icon(self, app_path: str) -> str:
|
||||
"""获取应用图标路径"""
|
||||
return self.icon_config.get_app_icon(app_path)
|
||||
|
||||
def set_app_icon(self, app_path: str, icon_path: str) -> bool:
|
||||
"""设置应用图标路径"""
|
||||
result = self.icon_config.set_app_icon(app_path, icon_path)
|
||||
if result:
|
||||
return self.save_config()
|
||||
return False
|
||||
|
||||
def remove_app_icon(self, app_path: str) -> bool:
|
||||
"""移除应用图标设置"""
|
||||
result = self.icon_config.remove_app_icon(app_path)
|
||||
if result:
|
||||
return self.save_config()
|
||||
return False
|
||||
|
||||
def get_all_app_icons(self) -> Dict[str, str]:
|
||||
"""获取所有应用图标映射"""
|
||||
return self.config_data.get("app_icons", {})
|
||||
|
||||
def get_app_color(self, app_path: str) -> str:
|
||||
"""获取应用按钮颜色"""
|
||||
return self.icon_config.get_app_color(app_path)
|
||||
|
||||
def set_app_color(self, app_path: str, color: str) -> bool:
|
||||
"""设置应用按钮颜色"""
|
||||
result = self.icon_config.set_app_color(app_path, color)
|
||||
if result:
|
||||
return self.save_config()
|
||||
return False
|
||||
|
||||
def remove_app_color(self, app_path: str) -> bool:
|
||||
"""移除应用按钮颜色设置"""
|
||||
result = self.icon_config.remove_app_color(app_path)
|
||||
if result:
|
||||
return self.save_config()
|
||||
return False
|
||||
|
||||
def get_all_app_colors(self) -> Dict[str, str]:
|
||||
"""获取所有应用按钮颜色映射"""
|
||||
return self.config_data.get("app_colors", {})
|
||||
|
||||
def get_icon_size(self) -> int:
|
||||
"""获取图标大小"""
|
||||
return self.config_data.get("icon_size", 80)
|
||||
|
||||
def save_icon_size(self, size: int) -> bool:
|
||||
"""保存图标大小"""
|
||||
self.config_data["icon_size"] = size
|
||||
return self.save_config()
|
||||
|
||||
def get_project_icon(self, project_name: str) -> str:
|
||||
"""获取项目图标路径"""
|
||||
return self.icon_config.get_project_icon(project_name)
|
||||
|
||||
def set_project_icon(self, project_name: str, icon_path: str) -> bool:
|
||||
"""设置项目图标路径"""
|
||||
result = self.icon_config.set_project_icon(project_name, icon_path)
|
||||
if result:
|
||||
return self.save_config()
|
||||
return False
|
||||
|
||||
def remove_project_icon(self, project_name: str) -> bool:
|
||||
"""移除项目图标设置"""
|
||||
result = self.icon_config.remove_project_icon(project_name)
|
||||
if result:
|
||||
return self.save_config()
|
||||
return False
|
||||
|
||||
def get_project_color(self, project_name: str) -> str:
|
||||
"""获取项目背景颜色"""
|
||||
return self.icon_config.get_project_color(project_name)
|
||||
|
||||
def set_project_color(self, project_name: str, color: str) -> bool:
|
||||
"""设置项目背景颜色"""
|
||||
result = self.icon_config.set_project_color(project_name, color)
|
||||
if result:
|
||||
return self.save_config()
|
||||
return False
|
||||
|
||||
def remove_project_color(self, project_name: str) -> bool:
|
||||
"""移除项目背景颜色设置"""
|
||||
result = self.icon_config.remove_project_color(project_name)
|
||||
if result:
|
||||
return self.save_config()
|
||||
return False
|
||||
|
||||
def _get_default_task_templates(self) -> Dict[str, List[str]]:
|
||||
"""获取默认任务类型文件夹模板"""
|
||||
return DEFAULT_TASK_FOLDER_TEMPLATES
|
||||
|
||||
def get_task_folder_template(self, task_type: str) -> List[str]:
|
||||
"""获取指定任务类型的文件夹模板
|
||||
|
||||
Args:
|
||||
task_type: 任务类型名称
|
||||
|
||||
Returns:
|
||||
文件夹路径列表
|
||||
"""
|
||||
templates = self.config_data.get("task_folder_templates", {})
|
||||
if task_type in templates:
|
||||
return templates[task_type]
|
||||
# 如果配置中没有,返回默认模板
|
||||
default_templates = self._get_default_task_templates()
|
||||
return default_templates.get(task_type, [])
|
||||
|
||||
def get_task_types(self) -> List[str]:
|
||||
"""获取所有可用的任务类型名称列表
|
||||
|
||||
Returns:
|
||||
任务类型名称列表
|
||||
"""
|
||||
templates = self.config_data.get("task_folder_templates", {})
|
||||
if not templates:
|
||||
# 如果配置中没有,使用默认模板
|
||||
templates = self._get_default_task_templates()
|
||||
return sorted(list(templates.keys()))
|
||||
|
||||
def get_all_task_folder_templates(self) -> Dict[str, List[str]]:
|
||||
"""获取所有任务类型的文件夹模板
|
||||
|
||||
Returns:
|
||||
任务类型到文件夹列表的映射
|
||||
"""
|
||||
templates = self.config_data.get("task_folder_templates", {})
|
||||
if not templates:
|
||||
# 如果配置中没有,初始化默认模板并保存
|
||||
templates = self._get_default_task_templates()
|
||||
self.config_data["task_folder_templates"] = templates
|
||||
self.save_config()
|
||||
return templates
|
||||
|
||||
def set_task_folder_template(self, task_type: str, folders: List[str]) -> bool:
|
||||
"""设置指定任务类型的文件夹模板
|
||||
|
||||
Args:
|
||||
task_type: 任务类型名称
|
||||
folders: 文件夹路径列表
|
||||
|
||||
Returns:
|
||||
是否保存成功
|
||||
"""
|
||||
if "task_folder_templates" not in self.config_data:
|
||||
self.config_data["task_folder_templates"] = {}
|
||||
|
||||
# 统一路径格式为正斜杠(JSON 存储格式)
|
||||
normalized_folders = [folder.replace("\\", "/") for folder in folders]
|
||||
self.config_data["task_folder_templates"][task_type] = normalized_folders
|
||||
return self.save_config()
|
||||
|
||||
def update_all_task_folder_templates(self, templates: Dict[str, List[str]]) -> bool:
|
||||
"""更新所有任务类型的文件夹模板
|
||||
|
||||
Args:
|
||||
templates: 任务类型到文件夹列表的映射
|
||||
|
||||
Returns:
|
||||
是否保存成功
|
||||
"""
|
||||
# 统一所有模板的路径格式为正斜杠(JSON 存储格式)
|
||||
normalized_templates = {}
|
||||
for task_type, folders in templates.items():
|
||||
normalized_templates[task_type] = [folder.replace("\\", "/") for folder in folders]
|
||||
|
||||
self.config_data["task_folder_templates"] = normalized_templates
|
||||
return self.save_config()
|
||||
|
||||
def get_task_settings(self, project_name: str) -> Dict:
|
||||
"""获取指定项目的 Task 面板设置
|
||||
|
||||
Args:
|
||||
project_name: 项目名称
|
||||
|
||||
Returns:
|
||||
Task 设置字典,包含 workspace, task_type, use_type_hierarchy
|
||||
"""
|
||||
# 确保 projects 字段存在
|
||||
if "projects" not in self.config_data:
|
||||
self.config_data["projects"] = {}
|
||||
|
||||
# 确保项目存在
|
||||
if project_name not in self.config_data["projects"]:
|
||||
self.config_data["projects"][project_name] = {}
|
||||
|
||||
# 从 projects.项目名.task_settings 读取
|
||||
project_data = self.config_data["projects"][project_name]
|
||||
settings = project_data.get("task_settings", {
|
||||
"workspace": "D:\\Workspace",
|
||||
"task_type": "Character",
|
||||
"use_type_hierarchy": False
|
||||
})
|
||||
|
||||
# 标准化路径格式(JSON中存储正斜杠,转换为反斜杠供UI显示)
|
||||
if "workspace" in settings and settings["workspace"]:
|
||||
settings["workspace"] = settings["workspace"].replace("/", "\\")
|
||||
if "maya_plugin_path" in settings and settings["maya_plugin_path"]:
|
||||
settings["maya_plugin_path"] = settings["maya_plugin_path"].replace("/", "\\")
|
||||
if "sp_shelf_path" in settings and settings["sp_shelf_path"]:
|
||||
settings["sp_shelf_path"] = settings["sp_shelf_path"].replace("/", "\\")
|
||||
|
||||
return settings
|
||||
|
||||
def set_task_settings(self, project_name: str, workspace: str = None,
|
||||
task_type: str = None, use_type_hierarchy: bool = None,
|
||||
maya_plugin_path: str = None, sp_shelf_path: str = None) -> bool:
|
||||
"""设置指定项目的 Task 面板设置
|
||||
|
||||
Args:
|
||||
project_name: 项目名称
|
||||
workspace: 工作空间路径
|
||||
task_type: 任务类型
|
||||
use_type_hierarchy: 是否使用类型层级
|
||||
maya_plugin_path: Maya 插件路径
|
||||
sp_shelf_path: Substance Painter 架子路径
|
||||
|
||||
Returns:
|
||||
是否保存成功
|
||||
"""
|
||||
# 确保 projects 字段存在
|
||||
if "projects" not in self.config_data:
|
||||
self.config_data["projects"] = {}
|
||||
|
||||
# 确保项目存在
|
||||
if project_name not in self.config_data["projects"]:
|
||||
self.config_data["projects"][project_name] = {}
|
||||
|
||||
# 确保 task_settings 字段存在
|
||||
if "task_settings" not in self.config_data["projects"][project_name]:
|
||||
self.config_data["projects"][project_name]["task_settings"] = {}
|
||||
|
||||
# 保存到 projects.项目名.task_settings
|
||||
settings = self.config_data["projects"][project_name]["task_settings"]
|
||||
|
||||
# 保存 SubFolders(如果存在,先临时保存)
|
||||
subfolders = settings.get("SubFolders")
|
||||
|
||||
# 按顺序更新字段
|
||||
if workspace is not None:
|
||||
settings["workspace"] = workspace.replace("\\", "/")
|
||||
if task_type is not None:
|
||||
settings["task_type"] = task_type
|
||||
if use_type_hierarchy is not None:
|
||||
settings["use_type_hierarchy"] = use_type_hierarchy
|
||||
if maya_plugin_path is not None:
|
||||
settings["maya_plugin_path"] = maya_plugin_path.replace("\\", "/")
|
||||
if sp_shelf_path is not None:
|
||||
settings["sp_shelf_path"] = sp_shelf_path.replace("\\", "/")
|
||||
|
||||
# 重新构建有序字典,确保字段顺序:workspace, maya_plugin_path, sp_shelf_path, task_type, use_type_hierarchy, SubFolders
|
||||
ordered_settings = {}
|
||||
for key in ["workspace", "maya_plugin_path", "sp_shelf_path", "task_type", "use_type_hierarchy"]:
|
||||
if key in settings:
|
||||
ordered_settings[key] = settings[key]
|
||||
|
||||
# 将 SubFolders 放在最后
|
||||
if subfolders is not None:
|
||||
ordered_settings["SubFolders"] = subfolders
|
||||
|
||||
# 替换原有的 task_settings
|
||||
self.config_data["projects"][project_name]["task_settings"] = ordered_settings
|
||||
|
||||
print(f"[OK] Save the task settings to projects.{project_name}.task_settings")
|
||||
return self.save_config()
|
||||
|
||||
def copy_apps_to_config(self, apps_data: List[Dict]) -> bool:
|
||||
"""将复制的应用数据保存到配置文件"""
|
||||
try:
|
||||
if "clipboard" not in self.config_data:
|
||||
self.config_data["clipboard"] = {}
|
||||
|
||||
self.config_data["clipboard"]["apps"] = apps_data
|
||||
print(f"[DEBUG] Saved {len(apps_data)} apps to config clipboard")
|
||||
return self.save_config()
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Failed to save apps to config clipboard: {e}")
|
||||
return False
|
||||
|
||||
def get_clipboard_apps(self) -> List[Dict]:
|
||||
"""从配置文件获取复制的应用数据"""
|
||||
try:
|
||||
if "clipboard" in self.config_data and "apps" in self.config_data["clipboard"]:
|
||||
apps = self.config_data["clipboard"]["apps"]
|
||||
print(f"[DEBUG] Retrieved {len(apps)} apps from config clipboard")
|
||||
return apps
|
||||
else:
|
||||
print("[DEBUG] No apps in config clipboard")
|
||||
return []
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Failed to get apps from config clipboard: {e}")
|
||||
return []
|
||||
|
||||
def clear_clipboard_apps(self) -> bool:
|
||||
"""清空配置文件中的应用剪贴板"""
|
||||
try:
|
||||
if "clipboard" in self.config_data:
|
||||
self.config_data["clipboard"]["apps"] = []
|
||||
print("[DEBUG] Cleared config clipboard")
|
||||
return self.save_config()
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Failed to clear config clipboard: {e}")
|
||||
return False
|
||||
|
||||
def save_selection_state(self, project_name: str, selected_indices: List[int]) -> bool:
|
||||
"""保存项目的选择状态到配置文件"""
|
||||
try:
|
||||
if "selection_states" not in self.config_data:
|
||||
self.config_data["selection_states"] = {}
|
||||
|
||||
self.config_data["selection_states"][project_name] = selected_indices
|
||||
print(f"[DEBUG] Saved selection state for {project_name}: {selected_indices}")
|
||||
return self.save_config()
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Failed to save selection state: {e}")
|
||||
return False
|
||||
|
||||
def get_selection_state(self, project_name: str) -> List[int]:
|
||||
"""从配置文件获取项目的选择状态"""
|
||||
try:
|
||||
if ("selection_states" in self.config_data and
|
||||
project_name in self.config_data["selection_states"]):
|
||||
indices = self.config_data["selection_states"][project_name]
|
||||
print(f"[DEBUG] Retrieved selection state for {project_name}: {indices}")
|
||||
return indices
|
||||
else:
|
||||
print(f"[DEBUG] No selection state found for {project_name}")
|
||||
return []
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Failed to get selection state: {e}")
|
||||
return []
|
||||
|
||||
def select_all_apps(self, project_name: str) -> List[int]:
|
||||
"""选择项目的所有应用并保存状态"""
|
||||
try:
|
||||
apps = self.get_apps(project_name)
|
||||
all_indices = list(range(len(apps)))
|
||||
self.save_selection_state(project_name, all_indices)
|
||||
print(f"[DEBUG] Selected all {len(all_indices)} apps in {project_name}")
|
||||
return all_indices
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Failed to select all apps: {e}")
|
||||
return []
|
||||
|
||||
def clear_selection_state(self, project_name: str) -> bool:
|
||||
"""清空项目的选择状态"""
|
||||
try:
|
||||
if ("selection_states" in self.config_data and
|
||||
project_name in self.config_data["selection_states"]):
|
||||
self.config_data["selection_states"][project_name] = []
|
||||
print(f"[DEBUG] Cleared selection state for {project_name}")
|
||||
return self.save_config()
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Failed to clear selection state: {e}")
|
||||
return False
|
||||
383
config/constants.py
Normal file
383
config/constants.py
Normal file
@@ -0,0 +1,383 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Application Constants
|
||||
--------------------
|
||||
应用程序的常量定义,按功能模块分类
|
||||
"""
|
||||
# ==================== 默认路径 ====================
|
||||
|
||||
# 默认项目文件夹路径
|
||||
DEFAULT_WORKSPACE_PATH = "D:\\Workspace"
|
||||
|
||||
# 默认Maya插件文件夹路径
|
||||
DEFAULT_MAYA_PLUGINS_PATH = "D:\\Plugins\\Maya"
|
||||
|
||||
# 默认SPShelf文件夹路径
|
||||
DEFAULT_SP_SHELF_PATH = "D:\\Plugins\\SPShelf"
|
||||
|
||||
# ==================== 项目模板配置 ====================
|
||||
|
||||
# 默认任务类型文件夹模板
|
||||
|
||||
DEFAULT_TASK_FOLDER_TEMPLATES = {
|
||||
"Character": [
|
||||
"Reference",
|
||||
"MP",
|
||||
"HP",
|
||||
"LP",
|
||||
"Baking",
|
||||
"Baking/HP",
|
||||
"Baking/LP",
|
||||
"Texture",
|
||||
"Texture/MeshMaps",
|
||||
"Texture/SP",
|
||||
"FBX",
|
||||
"Screenshot"
|
||||
],
|
||||
"Weapon": [
|
||||
"Reference",
|
||||
"MP",
|
||||
"HP",
|
||||
"LP",
|
||||
"Baking",
|
||||
"Baking/HP",
|
||||
"Baking/LP",
|
||||
"Texture",
|
||||
"Texture/MeshMaps",
|
||||
"Texture/SP",
|
||||
"FBX",
|
||||
"Screenshot"
|
||||
],
|
||||
"Prop": [
|
||||
"Reference",
|
||||
"MP",
|
||||
"HP",
|
||||
"LP",
|
||||
"Baking",
|
||||
"Baking/HP",
|
||||
"Baking/LP",
|
||||
"Texture",
|
||||
"Texture/MeshMaps",
|
||||
"Texture/SP",
|
||||
"FBX",
|
||||
"Screenshot"
|
||||
],
|
||||
"Environment": [
|
||||
"Reference",
|
||||
"MP",
|
||||
"HP",
|
||||
"LP",
|
||||
"Baking",
|
||||
"Baking/HP",
|
||||
"Baking/LP",
|
||||
"Texture",
|
||||
"Texture/MeshMaps",
|
||||
"Texture/SP",
|
||||
"FBX",
|
||||
"Screenshot"
|
||||
],
|
||||
"Animation": [
|
||||
"Reference",
|
||||
"Maya",
|
||||
"FBX",
|
||||
"Mocap"
|
||||
],
|
||||
"Rigging": [
|
||||
"Source",
|
||||
"Maya",
|
||||
"FBX"
|
||||
],
|
||||
"Other": [
|
||||
"Reference",
|
||||
"MP",
|
||||
"HP",
|
||||
"LP",
|
||||
"Baking",
|
||||
"Baking/HP",
|
||||
"Baking/LP",
|
||||
"Texture",
|
||||
"Texture/MeshMaps",
|
||||
"Texture/SP",
|
||||
"FBX",
|
||||
"Screenshot"
|
||||
]
|
||||
}
|
||||
|
||||
# ==================== 图标映射配置 ====================
|
||||
|
||||
# 应用名称到图标的映射
|
||||
APP_ICON_MAPPING = {
|
||||
"maya": "Maya",
|
||||
"maya2025": "Maya",
|
||||
"maya2026": "Maya",
|
||||
"maya2027": "Maya",
|
||||
"maya2028": "Maya",
|
||||
"maya2029": "Maya",
|
||||
"maya2020": "Maya",
|
||||
"maya2021": "Maya",
|
||||
"maya2022": "Maya",
|
||||
"maya2023": "Maya",
|
||||
"maya2024": "Maya",
|
||||
"ma": "Maya",
|
||||
"3dsmax": "3DsMax",
|
||||
"3ds": "3DsMax",
|
||||
"3ds-max": "3DsMax",
|
||||
"max": "3DsMax",
|
||||
"blender": "Blender",
|
||||
"photoshop": "Photoshop",
|
||||
"painter": "SubstancePainter",
|
||||
"3dpainter": "SubstancePainter",
|
||||
"substancepainter": "SubstancePainter",
|
||||
"substance3dpainter": "SubstancePainter",
|
||||
"sp": "SubstancePainter",
|
||||
"designer": "SubstanceDesigner",
|
||||
"3ddesigner": "SubstanceDesigner",
|
||||
"substancedesigner": "SubstanceDesigner",
|
||||
"substance3ddesigner": "SubstanceDesigner",
|
||||
"sd": "SubstanceDesigner",
|
||||
"marvelousdesigner": "MarvelousDesigner",
|
||||
"marvelous": "MarvelousDesigner",
|
||||
"md": "MarvelousDesigner",
|
||||
"marvelousdesigner": "MarvelousDesigner",
|
||||
"marvelous": "MarvelousDesigner",
|
||||
"rizom": "RizomUV",
|
||||
"rizomuv": "RizomUV",
|
||||
"zbrush": "Zbrush",
|
||||
"ue": "UnrealEngine",
|
||||
"ue4": "UnrealEngine",
|
||||
"ue5": "UnrealEngine",
|
||||
"ue6": "UnrealEngine",
|
||||
"unrealengine": "UnrealEngine",
|
||||
"unrealtoolbox": "UnrealEngine",
|
||||
"unrealgamesync": "UnrealGameSync",
|
||||
"ugs": "UnrealGameSync",
|
||||
"uefn": "UEFN",
|
||||
"marmoset": "MarmosetToolBag",
|
||||
"marmosettoolbag": "MarmosetToolBag",
|
||||
"toolbag": "MarmosetToolBag",
|
||||
"3dcoat": "3DCoat",
|
||||
"houdini": "Houdini",
|
||||
"houdinifx": "Houdini",
|
||||
"houdiniengine": "Houdini",
|
||||
"everything": "Everything",
|
||||
"billfish": "Billfish",
|
||||
"eagle": "Eagle"
|
||||
}
|
||||
|
||||
# ==================== 通用UI常量 ====================
|
||||
|
||||
# 预设颜色列表
|
||||
PRESET_COLORS = [
|
||||
"#607d8b", # 蓝灰色(默认)
|
||||
"#2196f3", # 蓝色
|
||||
"#f44336", # 红色
|
||||
"#4caf50", # 绿色
|
||||
"#ff9800", # 橙色
|
||||
"#9c27b0", # 紫色
|
||||
"#00bcd4", # 青色
|
||||
"#ffeb3b", # 黄色
|
||||
"#009688", # 青绿色
|
||||
"#673ab7", # 深紫色
|
||||
"#3f51b5", # 青蓝色
|
||||
"#795548" # 棕色
|
||||
]
|
||||
|
||||
# 基础颜色
|
||||
BG_COLOR_DARK = "#2b2b2b"
|
||||
BG_COLOR_LIGHT = "#3a3a3a"
|
||||
BG_COLOR_FRAME = "#3a3a3a"
|
||||
BG_COLOR_BUTTON = "#4a5568"
|
||||
BG_COLOR_BUTTON_HOVER = "#2d3748"
|
||||
COLOR_TRANSPARENT = "transparent"
|
||||
BORDER_COLOR = "#555555"
|
||||
BORDER_COLOR_WHITE = "#ffffff"
|
||||
LINE_COLOR_GRAY = "#aaaaaa"
|
||||
|
||||
# 文本颜色
|
||||
TEXT_COLOR_PRIMARY = "white"
|
||||
TEXT_COLOR_SECONDARY = "gray"
|
||||
TEXT_COLOR_WHITE = "#ffffff"
|
||||
|
||||
# 状态颜色
|
||||
COLOR_SUCCESS = "#28a745"
|
||||
COLOR_SUCCESS_HOVER = "#218838"
|
||||
COLOR_ERROR = "#dc3545"
|
||||
COLOR_ERROR_HOVER = "#c82333"
|
||||
COLOR_WARNING = "#ffc107"
|
||||
COLOR_INFO = "#17a2b8"
|
||||
|
||||
# 通用按钮颜色
|
||||
BUTTON_GRAY = "#757575"
|
||||
BUTTON_GRAY_HOVER = "#616161"
|
||||
BUTTON_RED = "#d32f2f"
|
||||
BUTTON_RED_HOVER = "#b71c1c"
|
||||
BUTTON_BLUE = "#2d6ba0"
|
||||
BUTTON_BLUE_HOVER = "#1d5b90"
|
||||
BUTTON_GREEN = "#3a8545"
|
||||
BUTTON_GREEN_HOVER = "#2a7535"
|
||||
|
||||
# 对话框颜色
|
||||
DIALOG_BG_COLOR = "#2b2b2b"
|
||||
DIALOG_TEXT_COLOR = "#e0e0e0"
|
||||
|
||||
# 拖拽和选择颜色
|
||||
DRAG_HIGHLIGHT_COLOR = "#3584e4"
|
||||
DRAG_HIGHLIGHT_BG = "#2a3f52"
|
||||
SELECTION_BORDER = "#1e5a96" # 更深的蓝色边框
|
||||
SELECTION_BG = "#2d3441" # 选择时的背景色(更亮一些,保持可读性)
|
||||
|
||||
# ==================== 主窗口常量 ====================
|
||||
|
||||
# 滚动条颜色 - 与卡片颜色统一
|
||||
SCROLLBAR_COLOR = "#2b2b2b" # 与卡片背景色一致
|
||||
SCROLLBAR_HOVER_COLOR = "#3a3a3a" # 悬停时稍亮一些
|
||||
|
||||
# 分段按钮颜色
|
||||
SEGMENTED_BUTTON_SELECTED_COLOR = "#4a5568"
|
||||
SEGMENTED_BUTTON_SELECTED_HOVER_COLOR = "#2d3748"
|
||||
SEGMENTED_BUTTON_UNSELECTED_COLOR = "#3a3a3a"
|
||||
SEGMENTED_BUTTON_UNSELECTED_HOVER_COLOR = "#4a4a4a"
|
||||
|
||||
# 下拉菜单颜色
|
||||
DROPDOWN_FG_COLOR = "#2b2b2b"
|
||||
DROPDOWN_HOVER_COLOR = "#4a5568"
|
||||
|
||||
# ==================== 项目管理面板常量 ====================
|
||||
|
||||
# 项目面板背景颜色(与任务面板保持一致)
|
||||
PROJECT_PANEL_BG_LIGHT = "#3B4252"
|
||||
PROJECT_PANEL_BG_DARK = "#2E3440"
|
||||
|
||||
# ==================== 设置窗口常量 ====================
|
||||
|
||||
# 特殊按钮颜色
|
||||
SAVE_BUTTON_COLOR = "#2e7d32"
|
||||
SAVE_BUTTON_HOVER = "#1b5e20"
|
||||
SAVE_BUTTON_BORDER = "#34d058"
|
||||
|
||||
# ==================== 任务管理面板常量 ====================
|
||||
|
||||
# 任务面板颜色
|
||||
TASK_PANEL_BG_LIGHT = "#3B4252"
|
||||
TASK_PANEL_BG_DARK = "#2E3440"
|
||||
|
||||
# 重置按钮颜色
|
||||
RESET_BUTTON_BORDER = "#868e96"
|
||||
|
||||
# ==================== 节点编辑器常量 ====================
|
||||
|
||||
# 画布和网格颜色
|
||||
NODE_CANVAS_BG = "#1a202c"
|
||||
NODE_GRID_COLOR = "#2d3748"
|
||||
|
||||
# 节点颜色
|
||||
NODE_BG_COLOR = "#2d2d2d"
|
||||
NODE_BORDER_COLOR = "#3a3a3a"
|
||||
NODE_SELECTED_BORDER = "#00d9ff"
|
||||
NODE_ID_TEXT_COLOR = "#888888"
|
||||
|
||||
# 连接点和连接线颜色
|
||||
NODE_INPUT_COLOR = "#5a9fd4"
|
||||
NODE_OUTPUT_COLOR = "#10b981"
|
||||
NODE_CONNECTION_COLOR = "#5a9fd4"
|
||||
NODE_CONNECTION_SELECTED = "#ff6b6b"
|
||||
|
||||
# 节点颜色调色板
|
||||
NODE_COLOR_PALETTE = [
|
||||
"#5a9fd4", # 蓝色
|
||||
"#10b981", # 绿色
|
||||
"#d97706", # 橙色
|
||||
"#dc2626", # 红色
|
||||
"#8b5cf6", # 紫色
|
||||
"#ec4899", # 粉色
|
||||
"#06b6d4", # 青色
|
||||
"#f59e0b", # 黄色
|
||||
"#6366f1", # 靛蓝
|
||||
"#14b8a6", # 青绿
|
||||
"#f97316", # 深橙
|
||||
"#a855f7", # 紫罗兰
|
||||
]
|
||||
|
||||
# ==================== 通用尺寸常量 ====================
|
||||
|
||||
# 窗口尺寸常量
|
||||
# 主窗口尺寸
|
||||
CONSOLE_WINDOW_SIZE = "600x400"
|
||||
|
||||
# 设置窗口尺寸
|
||||
SETTINGS_WINDOW_SIZE = "650x800"
|
||||
|
||||
# SubFolder Editor 窗口尺寸
|
||||
SUBFOLDER_EDITOR_WINDOW_SIZE = "1200x900"
|
||||
SUBFOLDER_EDITOR_MIN_SIZE = (1000, 800)
|
||||
|
||||
# 对话框尺寸
|
||||
DIALOG_INPUT_SIZE = "400x220"
|
||||
DIALOG_CONFIRM_SIZE = "450x200"
|
||||
DIALOG_APP_EDIT_SIZE = "650x700"
|
||||
DIALOG_ICON_SELECT_SIZE = "600x400"
|
||||
DIALOG_MESSAGE_SIZE = "400x250"
|
||||
DIALOG_YES_NO_SIZE = "450x250"
|
||||
DIALOG_NODE_RENAME_SIZE = "400x180"
|
||||
|
||||
# 对话框尺寸 (width, height) - 保持向后兼容
|
||||
DIALOG_SIZE_SMALL = (400, 220)
|
||||
DIALOG_SIZE_MEDIUM = (450, 200)
|
||||
DIALOG_SIZE_LARGE = (650, 700)
|
||||
DIALOG_SIZE_XLARGE = (600, 400)
|
||||
|
||||
# 图标尺寸
|
||||
ICON_SIZE_TINY = 1
|
||||
ICON_SIZE_SMALL = 22
|
||||
ICON_SIZE_MEDIUM = 48
|
||||
ICON_SIZE_LARGE = 64
|
||||
ICON_SIZE_XLARGE = 128
|
||||
|
||||
# 按钮尺寸
|
||||
BUTTON_WIDTH_SMALL = 80
|
||||
BUTTON_WIDTH_MEDIUM = 100
|
||||
BUTTON_WIDTH_LARGE = 120
|
||||
BUTTON_HEIGHT_SMALL = 30
|
||||
BUTTON_HEIGHT_MEDIUM = 40
|
||||
|
||||
# 圆角半径
|
||||
CORNER_RADIUS_SMALL = 8
|
||||
CORNER_RADIUS_MEDIUM = 10
|
||||
CORNER_RADIUS_LARGE = 15
|
||||
|
||||
# 间距
|
||||
PADDING_SMALL = 5
|
||||
PADDING_MEDIUM = 10
|
||||
PADDING_LARGE = 20
|
||||
|
||||
# ==================== 字体常量 ====================
|
||||
|
||||
FONT_SIZE_TINY = 8
|
||||
FONT_SIZE_SMALL = 10
|
||||
FONT_SIZE_MEDIUM = 12
|
||||
FONT_SIZE_LARGE = 13
|
||||
FONT_SIZE_XLARGE = 16
|
||||
|
||||
# ==================== 应用配置常量 ====================
|
||||
|
||||
# 图标延迟设置时间
|
||||
ICON_DELAY_SHORT = 10
|
||||
ICON_DELAY_MEDIUM = 50
|
||||
ICON_DELAY_LONG = 200
|
||||
|
||||
# 默认窗口设置
|
||||
DEFAULT_ICON_SIZE = 80
|
||||
MIN_ICON_SIZE = 50
|
||||
MAX_ICON_SIZE = 150
|
||||
DEFAULT_WINDOW_WIDTH = 425
|
||||
DEFAULT_WINDOW_HEIGHT = 480
|
||||
MIN_WINDOW_WIDTH = 200
|
||||
MIN_WINDOW_HEIGHT = 200
|
||||
|
||||
# 任务栏高度(用于窗口定位)
|
||||
TASKBAR_HEIGHT = 80
|
||||
|
||||
# 网格列数
|
||||
MAX_GRID_COLUMNS = 7
|
||||
DEFAULT_GRID_COLUMNS = 3
|
||||
312
config/icon_config.py
Normal file
312
config/icon_config.py
Normal file
@@ -0,0 +1,312 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
图标和颜色配置管理器
|
||||
负责管理应用和项目的图标、颜色配置
|
||||
"""
|
||||
import os
|
||||
from typing import Dict, Optional
|
||||
|
||||
|
||||
class IconConfigManager:
|
||||
"""图标和颜色配置管理器"""
|
||||
|
||||
def __init__(self, config_data: Dict, get_icons_dir_func):
|
||||
"""
|
||||
初始化图标配置管理器
|
||||
|
||||
Args:
|
||||
config_data: 配置数据字典的引用
|
||||
get_icons_dir_func: 获取图标目录的函数
|
||||
"""
|
||||
self.config_data = config_data
|
||||
self._get_icons_dir = get_icons_dir_func
|
||||
|
||||
# ==================== 应用图标管理 ====================
|
||||
|
||||
def get_app_icon(self, app_path: str) -> str:
|
||||
"""
|
||||
获取应用图标路径
|
||||
|
||||
如果配置中保存的是相对路径(只有文件名),则自动拼接 icons 目录
|
||||
|
||||
Args:
|
||||
app_path: 应用路径
|
||||
|
||||
Returns:
|
||||
图标的完整路径,如果不存在则返回空字符串
|
||||
"""
|
||||
icon_value = self.config_data.get("app_icons", {}).get(app_path, "")
|
||||
|
||||
if not icon_value:
|
||||
return ""
|
||||
|
||||
# 如果是绝对路径且存在,直接返回
|
||||
if os.path.isabs(icon_value) and os.path.exists(icon_value):
|
||||
return icon_value
|
||||
|
||||
# 如果是相对路径(只有文件名),拼接 icons 目录
|
||||
if not os.path.isabs(icon_value):
|
||||
icons_dir = self._get_icons_dir()
|
||||
full_path = os.path.join(icons_dir, icon_value)
|
||||
if os.path.exists(full_path):
|
||||
return full_path
|
||||
|
||||
# 如果都不存在,返回原值(可能是旧的绝对路径)
|
||||
return icon_value
|
||||
|
||||
def set_app_icon(self, app_path: str, icon_path: str) -> bool:
|
||||
"""
|
||||
设置应用图标路径
|
||||
|
||||
如果图标在 icons 目录下,只保存文件名(相对路径)
|
||||
否则保存完整路径
|
||||
|
||||
Args:
|
||||
app_path: 应用路径
|
||||
icon_path: 图标路径
|
||||
|
||||
Returns:
|
||||
是否设置成功
|
||||
"""
|
||||
if "app_icons" not in self.config_data:
|
||||
self.config_data["app_icons"] = {}
|
||||
|
||||
# 获取 icons 目录
|
||||
icons_dir = self._get_icons_dir()
|
||||
|
||||
# 如果图标在 icons 目录下,只保存文件名
|
||||
try:
|
||||
# 标准化路径以便比较
|
||||
icon_path_normalized = os.path.normpath(icon_path)
|
||||
icons_dir_normalized = os.path.normpath(icons_dir)
|
||||
|
||||
# 检查是否在 icons 目录下
|
||||
if icon_path_normalized.startswith(icons_dir_normalized):
|
||||
# 只保存文件名
|
||||
icon_filename = os.path.basename(icon_path)
|
||||
self.config_data["app_icons"][app_path] = icon_filename
|
||||
print(f"[OK] Saved icon as relative path: {icon_filename}")
|
||||
else:
|
||||
# 保存完整路径
|
||||
self.config_data["app_icons"][app_path] = icon_path
|
||||
print(f"[OK] Saved icon as absolute path: {icon_path}")
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"[WARNING] Error processing icon path: {e}")
|
||||
# 出错时保存完整路径
|
||||
self.config_data["app_icons"][app_path] = icon_path
|
||||
return False
|
||||
|
||||
def remove_app_icon(self, app_path: str) -> bool:
|
||||
"""
|
||||
移除应用图标设置
|
||||
|
||||
Args:
|
||||
app_path: 应用路径
|
||||
|
||||
Returns:
|
||||
是否移除成功
|
||||
"""
|
||||
if app_path in self.config_data.get("app_icons", {}):
|
||||
del self.config_data["app_icons"][app_path]
|
||||
return True
|
||||
return False
|
||||
|
||||
# ==================== 项目图标管理 ====================
|
||||
|
||||
def get_project_icon(self, project_name: str) -> str:
|
||||
"""
|
||||
获取项目图标路径
|
||||
|
||||
如果配置中保存的是相对路径(只有文件名),则自动拼接 icons 目录
|
||||
|
||||
Args:
|
||||
project_name: 项目名称
|
||||
|
||||
Returns:
|
||||
图标的完整路径,如果不存在则返回空字符串
|
||||
"""
|
||||
# 从项目配置中获取图标路径
|
||||
projects = self.config_data.get("projects", {})
|
||||
project_config = projects.get(project_name, {})
|
||||
icon_value = project_config.get("icon", "")
|
||||
|
||||
if not icon_value:
|
||||
return ""
|
||||
|
||||
# 如果是绝对路径且存在,直接返回
|
||||
if os.path.isabs(icon_value) and os.path.exists(icon_value):
|
||||
return icon_value
|
||||
|
||||
# 如果是相对路径(只有文件名),拼接 icons 目录
|
||||
if not os.path.isabs(icon_value):
|
||||
icons_dir = self._get_icons_dir()
|
||||
full_path = os.path.join(icons_dir, icon_value)
|
||||
if os.path.exists(full_path):
|
||||
return full_path
|
||||
|
||||
# 如果都不存在,返回原值(可能是旧的绝对路径)
|
||||
return icon_value
|
||||
|
||||
def set_project_icon(self, project_name: str, icon_path: str) -> bool:
|
||||
"""
|
||||
设置项目图标路径
|
||||
|
||||
如果图标在 icons 目录下,只保存文件名(相对路径)
|
||||
否则保存完整路径
|
||||
|
||||
Args:
|
||||
project_name: 项目名称
|
||||
icon_path: 图标路径
|
||||
|
||||
Returns:
|
||||
是否设置成功
|
||||
"""
|
||||
# 确保projects配置存在
|
||||
if "projects" not in self.config_data:
|
||||
self.config_data["projects"] = {}
|
||||
|
||||
# 确保项目配置存在
|
||||
if project_name not in self.config_data["projects"]:
|
||||
self.config_data["projects"][project_name] = {
|
||||
"apps": [],
|
||||
"icon": "",
|
||||
"color": ""
|
||||
}
|
||||
|
||||
# 获取 icons 目录
|
||||
icons_dir = self._get_icons_dir()
|
||||
|
||||
# 如果图标在 icons 目录下,只保存文件名
|
||||
try:
|
||||
# 标准化路径以便比较
|
||||
icon_path_normalized = os.path.normpath(icon_path)
|
||||
icons_dir_normalized = os.path.normpath(icons_dir)
|
||||
|
||||
# 检查是否在 icons 目录下
|
||||
if icon_path_normalized.startswith(icons_dir_normalized):
|
||||
# 只保存文件名
|
||||
icon_filename = os.path.basename(icon_path)
|
||||
self.config_data["projects"][project_name]["icon"] = icon_filename
|
||||
print(f"[OK] Saved project icon as relative path: {icon_filename}")
|
||||
else:
|
||||
# 保存完整路径
|
||||
self.config_data["projects"][project_name]["icon"] = icon_path
|
||||
print(f"[OK] Saved project icon as absolute path: {icon_path}")
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"[WARNING] Error processing project icon path: {e}")
|
||||
# 出错时保存完整路径
|
||||
self.config_data["projects"][project_name]["icon"] = icon_path
|
||||
return False
|
||||
|
||||
def remove_project_icon(self, project_name: str) -> bool:
|
||||
"""
|
||||
移除项目图标设置
|
||||
|
||||
Args:
|
||||
project_name: 项目名称
|
||||
|
||||
Returns:
|
||||
是否移除成功
|
||||
"""
|
||||
projects = self.config_data.get("projects", {})
|
||||
if project_name in projects and "icon" in projects[project_name]:
|
||||
projects[project_name]["icon"] = ""
|
||||
return True
|
||||
return False
|
||||
|
||||
# ==================== 应用颜色管理 ====================
|
||||
|
||||
def get_app_color(self, app_path: str) -> str:
|
||||
"""
|
||||
获取应用按钮颜色
|
||||
|
||||
Args:
|
||||
app_path: 应用路径
|
||||
|
||||
Returns:
|
||||
颜色值(十六进制),如果未设置则返回空字符串
|
||||
"""
|
||||
return self.config_data.get("app_colors", {}).get(app_path, "")
|
||||
|
||||
def set_app_color(self, app_path: str, color: str) -> bool:
|
||||
"""
|
||||
设置应用按钮颜色
|
||||
|
||||
Args:
|
||||
app_path: 应用路径
|
||||
color: 颜色值(十六进制)
|
||||
|
||||
Returns:
|
||||
是否设置成功
|
||||
"""
|
||||
if "app_colors" not in self.config_data:
|
||||
self.config_data["app_colors"] = {}
|
||||
|
||||
self.config_data["app_colors"][app_path] = color
|
||||
return True
|
||||
|
||||
def remove_app_color(self, app_path: str) -> bool:
|
||||
"""
|
||||
移除应用按钮颜色设置
|
||||
|
||||
Args:
|
||||
app_path: 应用路径
|
||||
|
||||
Returns:
|
||||
是否移除成功
|
||||
"""
|
||||
if app_path in self.config_data.get("app_colors", {}):
|
||||
del self.config_data["app_colors"][app_path]
|
||||
return True
|
||||
return False
|
||||
|
||||
# ==================== 项目颜色管理 ====================
|
||||
|
||||
def get_project_color(self, project_name: str) -> str:
|
||||
"""
|
||||
获取项目背景颜色
|
||||
|
||||
Args:
|
||||
project_name: 项目名称
|
||||
|
||||
Returns:
|
||||
颜色值(十六进制),默认为 #2b4c6f
|
||||
"""
|
||||
return self.config_data.get("project_colors", {}).get(project_name, "#2b4c6f")
|
||||
|
||||
def set_project_color(self, project_name: str, color: str) -> bool:
|
||||
"""
|
||||
设置项目背景颜色
|
||||
|
||||
Args:
|
||||
project_name: 项目名称
|
||||
color: 颜色值(十六进制)
|
||||
|
||||
Returns:
|
||||
是否设置成功
|
||||
"""
|
||||
if "project_colors" not in self.config_data:
|
||||
self.config_data["project_colors"] = {}
|
||||
|
||||
self.config_data["project_colors"][project_name] = color
|
||||
return True
|
||||
|
||||
def remove_project_color(self, project_name: str) -> bool:
|
||||
"""
|
||||
移除项目背景颜色设置
|
||||
|
||||
Args:
|
||||
project_name: 项目名称
|
||||
|
||||
Returns:
|
||||
是否移除成功
|
||||
"""
|
||||
if project_name in self.config_data.get("project_colors", {}):
|
||||
del self.config_data["project_colors"][project_name]
|
||||
return True
|
||||
return False
|
||||
Reference in New Issue
Block a user