my-kicad-user-folder/3rdparty/plugins/com_github_bennymeg_JLC-Plugin-for-KiCad/thread.py
2025-03-21 13:41:39 +08:00

159 lines
6.0 KiB
Python

import os
import wx
import pcbnew # type: ignore
import shutil
import tempfile
import webbrowser
import datetime
import logging
from threading import Thread
from .events import StatusEvent
from .process import ProcessManager
from .config import *
from .options import *
from .utils import print_cli_progress_bar
class ProcessThread(Thread):
def __init__(self, wx, options, cli = None, openBrowser = True):
Thread.__init__(self)
# prevent use of cli and grapgical mode at the same time
if (wx is None and cli is None) or (wx is not None and cli is not None):
logging.error("Specify either graphical or cli use!")
return
if cli is not None:
try:
self.board = pcbnew.LoadBoard(cli)
except Exception as e:
logging.error("Fabrication Toolkit - Error" + str(e))
return
else:
self.board = None
self.process_manager = ProcessManager(self.board)
self.wx = wx
self.cli = cli
self.options = options
self.openBrowser = openBrowser
self.start()
def run(self):
# initializing
self.progress(0)
temp_dir = tempfile.mkdtemp()
temp_dir_gerber = temp_dir + "_g"
os.makedirs(temp_dir_gerber)
_, temp_file = tempfile.mkstemp()
project_directory = os.path.dirname(self.process_manager.board.GetFileName())
try:
# Verify all zones are up-to-date
self.progress(10)
if (self.options[AUTO_FILL_OPT]):
self.process_manager.update_zone_fills()
# generate gerber
self.progress(20)
self.process_manager.generate_gerber(temp_dir_gerber, self.options[EXTRA_LAYERS], self.options[EXTEND_EDGE_CUT_OPT],
self.options[ALTERNATIVE_EDGE_CUT_OPT], self.options[ALL_ACTIVE_LAYERS_OPT])
# generate drill file
self.progress(30)
self.process_manager.generate_drills(temp_dir_gerber)
# generate netlist
self.progress(40)
self.process_manager.generate_netlist(temp_dir)
# generate data tables
self.progress(50)
self.process_manager.generate_tables(temp_dir, self.options[AUTO_TRANSLATE_OPT], self.options[EXCLUDE_DNP_OPT])
# generate pick and place file
self.progress(60)
self.process_manager.generate_positions(temp_dir)
# generate BOM file
self.progress(70)
self.process_manager.generate_bom(temp_dir)
# generate production archive
self.progress(85)
temp_file = self.process_manager.generate_archive(temp_dir_gerber, temp_file)
shutil.move(temp_file, temp_dir)
shutil.rmtree(temp_dir_gerber)
temp_file = os.path.join(temp_dir, os.path.basename(temp_file))
except Exception as e:
if self.wx is None:
logging.error("Fabrication Toolkit - Error" + str(e))
else:
wx.MessageBox(str(e), "Fabrication Toolkit - Error", wx.OK | wx.ICON_ERROR)
self.progress(-1)
return
# progress bar done animation
read_so_far = 0
total_size = os.path.getsize(temp_file)
with open(temp_file, 'rb') as file:
while True:
data = file.read(10)
if not data:
break
read_so_far += len(data)
percent = read_so_far * 1e2 / total_size
self.progress(85 + percent / 8)
# generate gerber name
title_block = self.process_manager.board.GetTitleBlock()
title = title_block.GetTitle()
revision = title_block.GetRevision()
company = title_block.GetCompany()
file_date = title_block.GetDate()
if (hasattr(self.process_manager.board, "GetProject") and hasattr(pcbnew, "ExpandTextVars")):
project = self.process_manager.board.GetProject()
title = pcbnew.ExpandTextVars(title, project)
revision = pcbnew.ExpandTextVars(revision, project)
company = pcbnew.ExpandTextVars(company, project)
file_date = pcbnew.ExpandTextVars(file_date, project)
# make output dir
filename = os.path.splitext(os.path.basename(self.process_manager.board.GetFileName()))[0]
output_path = os.path.join(project_directory, outputFolder)
if not os.path.exists(output_path):
os.makedirs(output_path)
# rename gerber archive
gerberArchiveName = ProcessManager.normalize_filename("_".join(("{} {}".format(title or filename, revision or '').strip() + '.zip').split()))
os.rename(temp_file, os.path.join(temp_dir, gerberArchiveName))
timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H-%M-%S')
backup_name = ProcessManager.normalize_filename("_".join(("{} {} {}".format(title or filename, revision or '', timestamp).strip()).split()))
shutil.make_archive(os.path.join(output_path, 'backups', backup_name), 'zip', temp_dir)
# copy to & open output dir
try:
shutil.copytree(temp_dir, output_path, dirs_exist_ok=True)
if self.openBrowser:
webbrowser.open("file://%s" % (output_path))
shutil.rmtree(temp_dir)
except Exception as e:
if self.openBrowser:
webbrowser.open("file://%s" % (temp_dir))
if self.wx is None:
self.progress(100)
else:
self.progress(-1)
def progress(self, percent):
if self.wx is None:
print_cli_progress_bar(percent, prefix = 'Progress:', suffix = 'Complete', length = 50)
else:
wx.PostEvent(self.wx, StatusEvent(percent))