MRobot/app/code_generate_interface.py
2025-08-05 03:47:11 +08:00

150 lines
5.8 KiB
Python

from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QSizePolicy, QTreeWidget, QTreeWidgetItem, QStackedWidget
from PyQt5.QtCore import Qt
from qfluentwidgets import TitleLabel, BodyLabel, PushButton
from app.tools.analyzing_ioc import analyzing_ioc
from app.code_page.bsp_interface import bsp
import os
import csv
import importlib
class CodeGenerateInterface(QWidget):
def __init__(self, project_path, parent=None):
super().__init__(parent)
self.setObjectName("CodeGenerateInterface")
self.project_path = project_path
self._init_ui()
def _init_ui(self):
"""初始化界面布局"""
main_layout = QVBoxLayout(self)
main_layout.setAlignment(Qt.AlignTop)
main_layout.setContentsMargins(10, 10, 10, 10)
top_layout = self._create_top_layout()
main_layout.addLayout(top_layout)
# 下方主区域,左右分栏
content_layout = QHBoxLayout()
content_layout.setContentsMargins(0, 10, 0, 0)
main_layout.addLayout(content_layout)
# 左侧树形列表
self.tree = QTreeWidget()
self.tree.setHeaderHidden(True)
self.tree.setMaximumWidth(250)
content_layout.addWidget(self.tree)
# 右侧内容区
self.stack = QStackedWidget()
content_layout.addWidget(self.stack)
self._load_csv_and_build_tree()
self.tree.itemClicked.connect(self.on_tree_item_clicked)
def _create_top_layout(self):
"""创建顶部横向布局"""
top_layout = QHBoxLayout()
top_layout.setAlignment(Qt.AlignTop)
# 项目名称标签
project_name = os.path.basename(self.project_path)
name_label = BodyLabel(f"项目名称: {project_name}")
name_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
top_layout.addWidget(name_label)
# FreeRTOS状态标签
freertos_label = BodyLabel(f"FreeRTOS: {self._get_freertos_status()}")
freertos_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
top_layout.addWidget(freertos_label)
# 生成代码按钮
generate_btn = PushButton("Generate Code")
generate_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
generate_btn.clicked.connect(self.generate_code)
top_layout.addWidget(generate_btn, alignment=Qt.AlignRight)
return top_layout
def generate_code(self):
"""生成代码逻辑"""
# 收集所有已加载的页面对象
pages = []
for i in range(self.stack.count()):
widget = self.stack.widget(i)
pages.append(widget)
bsp.generate_bsp(self.project_path, pages)
# component.generate_component(self.project_path)
# device.generate_device(self.project_path)
def _get_freertos_status(self):
"""获取FreeRTOS状态"""
ioc_files = [f for f in os.listdir(self.project_path) if f.endswith('.ioc')]
if ioc_files:
ioc_path = os.path.join(self.project_path, ioc_files[0])
return "开启" if analyzing_ioc.is_freertos_enabled_from_ioc(ioc_path) else "未开启"
return "未找到.ioc文件"
def _load_csv_and_build_tree(self):
# 获取脚本目录
script_dir = os.path.dirname(os.path.abspath(__file__))
csv_path = os.path.join(script_dir, "../assets/User_code/config.csv")
csv_path = os.path.abspath(csv_path)
print(f"加载CSV路径: {csv_path}")
if not os.path.exists(csv_path):
print(f"配置文件未找到: {csv_path}")
return
self.tree.clear()
with open(csv_path, newline='', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
row = [cell.strip() for cell in row if cell.strip()]
if not row:
continue
main_title = row[0]
main_item = QTreeWidgetItem([main_title])
for sub in row[1:]:
sub_item = QTreeWidgetItem([sub])
main_item.addChild(sub_item)
self.tree.addTopLevelItem(main_item)
self.tree.repaint()
def on_tree_item_clicked(self, item, column):
if item.parent():
main_title = item.parent().text(0)
sub_title = item.text(0)
class_name = f"{main_title}_{sub_title}".replace("-", "_")
widget = self._get_or_create_page(class_name)
if widget:
self.stack.setCurrentWidget(widget)
def _get_or_create_page(self, class_name):
for i in range(self.stack.count()):
w = self.stack.widget(i)
if w.objectName() == class_name:
return w
try:
module_name = f"app.code_page.{class_name.split('_')[0]}_interface"
module = importlib.import_module(module_name)
cls = getattr(module, class_name)
widget = cls(self.project_path)
widget.setObjectName(class_name)
self.stack.addWidget(widget)
print(f"加载页面类: {class_name} 来自模块: {module_name}")
return widget
except Exception as e:
# 自动识别通用外设页面
from app.code_page.bsp_interface import BspSimplePeripheral
peripheral_name = class_name.split('_')[1] if '_' in class_name else class_name
# 模板文件名自动推断
template_names = {
'header': f"{peripheral_name.lower()}.h",
'source': f"{peripheral_name.lower()}.c"
}
widget = BspSimplePeripheral(self.project_path, peripheral_name, template_names)
widget.setObjectName(class_name)
self.stack.addWidget(widget)
print(f"自动加载通用外设页面: {class_name}")
return widget