From 22b7d1416aee4ea16522138b821645c2fb9e2472 Mon Sep 17 00:00:00 2001 From: RB Date: Sun, 27 Apr 2025 01:55:59 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E5=A4=8D=E5=88=B6=E6=A8=A1?= =?UTF-8?q?=E7=BB=84=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MRobot.py | 281 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 MRobot.py diff --git a/MRobot.py b/MRobot.py new file mode 100644 index 0000000..06953e5 --- /dev/null +++ b/MRobot.py @@ -0,0 +1,281 @@ +import tkinter as tk +import os +import threading +import shutil +import re +from git import Repo + +# 配置常量 +REPO_DIR = "MRobot_repo" +REPO_URL = "http://gitea.qutrobot.top/robofish/MRobot.git" + +class MRobotApp: + def __init__(self): + self.ioc_data = None + self.add_gitignore_var = None # 延迟初始化 + self.header_file_vars = {} + + # 克隆仓库 + def clone_repo(self): + try: + if os.path.exists(REPO_DIR): + shutil.rmtree(REPO_DIR) + print(f"正在克隆仓库到 {REPO_DIR}...") + Repo.clone_from(REPO_URL, REPO_DIR) + print("仓库克隆成功!") + except Exception as e: + print(f"克隆仓库时出错: {e}") + + # 删除克隆的仓库 + def delete_repo(self): + try: + if os.path.exists(REPO_DIR): + shutil.rmtree(REPO_DIR) + print(f"已删除克隆的仓库目录: {REPO_DIR}") + except Exception as e: + print(f"删除仓库目录时出错: {e}") + + # 复制文件 + def copy_file_from_repo(self, src_path, dest_path): + try: + # 修复路径拼接问题,确保 src_path 不重复包含 REPO_DIR + if src_path.startswith(REPO_DIR): + full_src_path = src_path + else: + full_src_path = os.path.join(REPO_DIR, src_path.lstrip(os.sep)) + + # 检查源文件是否存在 + if not os.path.exists(full_src_path): + print(f"文件 {full_src_path} 不存在!(检查路径或仓库内容)") + return + + # 检查目标路径是否有效 + if not dest_path or not dest_path.strip(): + print("目标路径为空或无效,无法复制文件!") + return + + # 创建目标目录(如果不存在) + dest_dir = os.path.dirname(dest_path) + if dest_dir and not os.path.exists(dest_dir): + os.makedirs(dest_dir, exist_ok=True) + + # 执行文件复制 + shutil.copy(full_src_path, dest_path) + print(f"文件已从 {full_src_path} 复制到 {dest_path}") + except Exception as e: + print(f"复制文件时出错: {e}") + + # 查找并读取 .ioc 文件 + def find_and_read_ioc_file(self): + try: + for file in os.listdir("."): + if file.endswith(".ioc"): + print(f"找到 .ioc 文件: {file}") + with open(file, "r", encoding="utf-8") as f: + return f.read() + print("未找到 .ioc 文件!") + except Exception as e: + print(f"读取 .ioc 文件时出错: {e}") + return None + + # 检查是否启用了 FreeRTOS + def check_freertos_enabled(self, ioc_data): + try: + return bool(re.search(r"Mcu\.IP\d+=FREERTOS", ioc_data)) + except Exception as e: + print(f"检查 FreeRTOS 配置时出错: {e}") + return False + + # 生成操作 + def generate_action(self): + def task(): + # 检查并创建目录 + self.create_directories() + + if self.add_gitignore_var.get(): + self.copy_file_from_repo(".gitignore", ".gitignore") + if self.ioc_data and self.check_freertos_enabled(self.ioc_data): + self.copy_file_from_repo("src/freertos.c", os.path.join("Core", "Src", "freertos.c")) + + # 定义需要处理的文件夹 + folders = ["bsp", "component", "device", "module"] + + for folder in folders: + folder_dir = os.path.join(REPO_DIR, "User", folder) + for file_name, var in self.header_file_vars.items(): + if var.get(): + # 复制 .h 文件 + h_file_src = os.path.join(folder_dir, f"{file_name}.h") + h_file_dest = os.path.join("User", folder, f"{file_name}.h") + self.copy_file_from_repo(h_file_src, h_file_dest) + + # 复制同名 .c 文件(如果存在) + c_file_src = os.path.join(folder_dir, f"{file_name}.c") + c_file_dest = os.path.join("User", folder, f"{file_name}.c") + if os.path.exists(c_file_src): + self.copy_file_from_repo(c_file_src, c_file_dest) + + threading.Thread(target=task).start() + + # 创建必要的目录 + def create_directories(self): + try: + directories = [ + "User/bsp", + "User/component", + "User/device", + "User/module", + ] + # 根据是否启用 FreeRTOS 决定是否创建 User/task + if self.ioc_data and self.check_freertos_enabled(self.ioc_data): + directories.append("User/task") + + for directory in directories: + if not os.path.exists(directory): + os.makedirs(directory, exist_ok=True) + print(f"已创建目录: {directory}") + else: + print(f"目录已存在: {directory}") + except Exception as e: + print(f"创建目录时出错: {e}") + + # 更新 FreeRTOS 状态标签 + def update_freertos_status(self, label): + if self.ioc_data: + status = "已启用" if self.check_freertos_enabled(self.ioc_data) else "未启用" + else: + status = "未检测到 .ioc 文件" + label.config(text=f"FreeRTOS 状态: {status}") + + # 初始化 + def initialize(self): + print("初始化中,正在克隆仓库...") + self.clone_repo() + self.ioc_data = self.find_and_read_ioc_file() + print("初始化完成,启动主窗口...") + self.show_main_window() + + # 显示主窗口 + def show_main_window(self): + root = tk.Tk() + root.title("MRobot自动生成脚本") + root.geometry("700x700") # 调整窗口大小 + + # 初始化 BooleanVar + self.add_gitignore_var = tk.BooleanVar(value=True) + + # 添加标题 + title_label = tk.Label(root, text="MRobot 自动生成脚本", font=("Arial", 16, "bold")) + title_label.pack(pady=10) + + # 添加复选框 + gitignore_frame = tk.Frame(root) + gitignore_frame.pack(pady=10) + tk.Checkbutton(gitignore_frame, text="添加 .gitignore", variable=self.add_gitignore_var).pack(anchor="w") + + # 添加 FreeRTOS 状态标签 + freertos_status_label = tk.Label(root, text="FreeRTOS 状态: 检测中...", font=("Arial", 12)) + freertos_status_label.pack(pady=10) + self.update_freertos_status(freertos_status_label) + + # 显示 .h 文件复选框 + header_files_frame = tk.LabelFrame(root, text="模块文件选择", padx=10, pady=10, font=("Arial", 10, "bold")) + header_files_frame.pack(pady=10, fill="both", expand=True) + self.header_files_frame = header_files_frame + self.update_header_files() + + # 添加生成按钮 + button_frame = tk.Frame(root) + button_frame.pack(pady=20) + generate_button = tk.Button(button_frame, text="一键自动生成MR架构", command=self.generate_action, bg="green", fg="white", font=("Arial", 12, "bold")) + generate_button.pack() + + # 在程序关闭时清理 + root.protocol("WM_DELETE_WINDOW", lambda: self.on_closing(root)) + root.mainloop() + + # 更新文件夹显示 + def update_folder_display(self): + for widget in self.folder_frame.winfo_children(): + widget.destroy() + + folders = ["User/bsp", "User/component", "User/device", "User/module"] + # if self.ioc_data and self.check_freertos_enabled(self.ioc_data): + # folders.append("User/task") + + for folder in folders: + # 去掉 "User/" 前缀 + display_name = folder.replace("User/", "") + tk.Label(self.folder_frame, text=display_name).pack() + + # 更新 .h 文件复选框 + def update_header_files(self): + for widget in self.header_files_frame.winfo_children(): + widget.destroy() + + # 定义需要处理的文件夹 + folders = ["bsp", "component", "device", "module"] + + for folder in folders: + folder_dir = os.path.join(REPO_DIR, "User", folder) + if os.path.exists(folder_dir): + # 创建每个模块的分组框 + module_frame = tk.LabelFrame(self.header_files_frame, text=folder.capitalize(), padx=10, pady=10, font=("Arial", 10, "bold")) + module_frame.pack(fill="x", pady=5) + + # 创建一个横向布局的容器 + row_frame = tk.Frame(module_frame) + row_frame.pack(fill="x", pady=5) + + for file in os.listdir(folder_dir): + if file.endswith(".h"): + file_name_without_extension = os.path.splitext(file)[0] # 去掉 .h 后缀 + var = tk.BooleanVar(value=False) + self.header_file_vars[file_name_without_extension] = var + # 显示复选框,横向排列 + tk.Checkbutton( + row_frame, + text=file_name_without_extension, + variable=var + ).pack(side="left", padx=5, pady=5) + # 生成操作 + def generate_action(self): + def task(): + # 检查并创建目录 + self.create_directories() + + if self.add_gitignore_var.get(): + self.copy_file_from_repo(".gitignore", ".gitignore") + if self.ioc_data and self.check_freertos_enabled(self.ioc_data): + self.copy_file_from_repo("src/freertos.c", os.path.join("Core", "Src", "freertos.c")) + + # 定义需要处理的文件夹 + folders = ["bsp", "component", "device", "module"] + + # 遍历每个文件夹,复制选中的 .h 和 .c 文件 + for folder in folders: + folder_dir = os.path.join(REPO_DIR, "User", folder) + if not os.path.exists(folder_dir): + continue # 如果文件夹不存在,跳过 + + for file_name in os.listdir(folder_dir): + file_base, file_ext = os.path.splitext(file_name) + if file_ext not in [".h", ".c"]: + continue # 只处理 .h 和 .c 文件 + + # 检查是否选中了对应的文件 + if file_base in self.header_file_vars and self.header_file_vars[file_base].get(): + src_path = os.path.join(folder_dir, file_name) + dest_path = os.path.join("User", folder, file_name) + self.copy_file_from_repo(src_path, dest_path) + + threading.Thread(target=task).start() + # 程序关闭时清理 + def on_closing(self, root): + self.delete_repo() + root.destroy() + +# 程序入口 +if __name__ == "__main__": + app = MRobotApp() + app.initialize() \ No newline at end of file