project.py•7.43 kB
"""
Project-related command implementations for KiCAD interface
"""
import os
import pcbnew # type: ignore
import logging
from typing import Dict, Any, Optional
logger = logging.getLogger('kicad_interface')
class ProjectCommands:
"""Handles project-related KiCAD operations"""
def __init__(self, board: Optional[pcbnew.BOARD] = None):
"""Initialize with optional board instance"""
self.board = board
def create_project(self, params: Dict[str, Any]) -> Dict[str, Any]:
"""Create a new KiCAD project"""
try:
project_name = params.get("projectName", "New_Project")
path = params.get("path", os.getcwd())
template = params.get("template")
# Generate the full project path
project_path = os.path.join(path, project_name)
if not project_path.endswith(".kicad_pro"):
project_path += ".kicad_pro"
# Create project directory if it doesn't exist
os.makedirs(os.path.dirname(project_path), exist_ok=True)
# Create a new board
board = pcbnew.BOARD()
# Set project properties
board.GetTitleBlock().SetTitle(project_name)
# Set current date with proper parameter
from datetime import datetime
current_date = datetime.now().strftime("%Y-%m-%d")
board.GetTitleBlock().SetDate(current_date)
# If template is specified, try to load it
if template:
template_path = os.path.expanduser(template)
if os.path.exists(template_path):
template_board = pcbnew.LoadBoard(template_path)
# Copy settings from template
board.SetDesignSettings(template_board.GetDesignSettings())
board.SetLayerStack(template_board.GetLayerStack())
# Save the board
board_path = project_path.replace(".kicad_pro", ".kicad_pcb")
board.SetFileName(board_path)
pcbnew.SaveBoard(board_path, board)
# Create project file
with open(project_path, 'w') as f:
f.write('{\n')
f.write(' "board": {\n')
f.write(f' "filename": "{os.path.basename(board_path)}"\n')
f.write(' }\n')
f.write('}\n')
self.board = board
return {
"success": True,
"message": f"Created project: {project_name}",
"project": {
"name": project_name,
"path": project_path,
"boardPath": board_path
}
}
except Exception as e:
logger.error(f"Error creating project: {str(e)}")
return {
"success": False,
"message": "Failed to create project",
"errorDetails": str(e)
}
def open_project(self, params: Dict[str, Any]) -> Dict[str, Any]:
"""Open an existing KiCAD project"""
try:
filename = params.get("filename")
if not filename:
return {
"success": False,
"message": "No filename provided",
"errorDetails": "The filename parameter is required"
}
# Expand user path and make absolute
filename = os.path.abspath(os.path.expanduser(filename))
# If it's a project file, get the board file
if filename.endswith(".kicad_pro"):
board_path = filename.replace(".kicad_pro", ".kicad_pcb")
else:
board_path = filename
# Load the board
board = pcbnew.LoadBoard(board_path)
self.board = board
return {
"success": True,
"message": f"Opened project: {os.path.basename(board_path)}",
"project": {
"name": os.path.splitext(os.path.basename(board_path))[0],
"path": filename,
"boardPath": board_path
}
}
except Exception as e:
logger.error(f"Error opening project: {str(e)}")
return {
"success": False,
"message": "Failed to open project",
"errorDetails": str(e)
}
def save_project(self, params: Dict[str, Any]) -> Dict[str, Any]:
"""Save the current KiCAD project"""
try:
if not self.board:
return {
"success": False,
"message": "No board is loaded",
"errorDetails": "Load or create a board first"
}
filename = params.get("filename")
if filename:
# Save to new location
filename = os.path.abspath(os.path.expanduser(filename))
self.board.SetFileName(filename)
# Save the board
pcbnew.SaveBoard(self.board.GetFileName(), self.board)
return {
"success": True,
"message": f"Saved project to: {self.board.GetFileName()}",
"project": {
"name": os.path.splitext(os.path.basename(self.board.GetFileName()))[0],
"path": self.board.GetFileName()
}
}
except Exception as e:
logger.error(f"Error saving project: {str(e)}")
return {
"success": False,
"message": "Failed to save project",
"errorDetails": str(e)
}
def get_project_info(self, params: Dict[str, Any]) -> Dict[str, Any]:
"""Get information about the current project"""
try:
if not self.board:
return {
"success": False,
"message": "No board is loaded",
"errorDetails": "Load or create a board first"
}
title_block = self.board.GetTitleBlock()
filename = self.board.GetFileName()
return {
"success": True,
"project": {
"name": os.path.splitext(os.path.basename(filename))[0],
"path": filename,
"title": title_block.GetTitle(),
"date": title_block.GetDate(),
"revision": title_block.GetRevision(),
"company": title_block.GetCompany(),
"comment1": title_block.GetComment(0),
"comment2": title_block.GetComment(1),
"comment3": title_block.GetComment(2),
"comment4": title_block.GetComment(3)
}
}
except Exception as e:
logger.error(f"Error getting project info: {str(e)}")
return {
"success": False,
"message": "Failed to get project information",
"errorDetails": str(e)
}