KiCad Pin Extraction Plugin: Developer Documentation - wayri/KiCAD_Plugins_Wayri GitHub Wiki
This document provides an exhaustive overview of the KiCad Pin Extraction Plugin, including full source code, embedded diagrams, detailed explanations of every method, class, UI element, and customization tips. Treat this as a one-stop reference for both users and developers.
- Purpose & Features
- Diagrams
- Source Code Files
- Line-by-Line Explanation
- Customization & Extension
- Downloadable Markdown
The KiCad Pin Extraction Plugin enables engineers to:
- Select footprints on a PCB in KiCad.
- Filter by component value, net names, connector types.
-
Export pin data to:
- Markdown with optional colored net highlighting.
- CSV for data processing.
- Non-modal GUI: interact with KiCad while dialog is open.
- User selects footprints in KiCad PCB editor.
- Launch plugin via Tools โ External Plugins or toolbar button.
- PluginDialog appears.
- User applies filters, views details, and clicks export.
- Plugin saves
.md
,.csv
Below is an overview of how the pluginโs modules interact:
__init__.py # Registers plugin with KiCad
extract_pins_plugin.py # Defines the ActionPlugin entry point, gathers initial selection, launches GUI
plugin_dialog.py # Implements the full wxPython dialog, data extraction, filtering, export logic
help_doc.html # External HTML help file opened by the Help button
# Registers the plugin on import
from .extract_pins_plugin import ExtractPinsPlugin
# Instantiate and register with KiCad
ExtractPinsPlugin().register()
import pcbnew
import wx
import os
from .plugin_dialog import PluginDialog
class ExtractPinsPlugin(pcbnew.ActionPlugin):
"""
KiCad ActionPlugin to launch the pin extraction GUI.
"""
def defaults(self):
# Metadata displayed in KiCad
self.name = "Extract Component Pins with GUI"
self.category = "Utilities"
self.description = (
"Opens a GUI to extract pin data and highlight nets "
"from selected footprints."
)
self.show_toolbar_button = True
# Icon file (optional)
self.icon_file_name = os.path.join(
os.path.dirname(__file__), 'epp_favicon.png'
)
self.version = "1.1.0"
def Run(self):
"""
Called when user activates the plugin.
Retrieves selected footprints; opens dialog.
"""
board = pcbnew.GetBoard()
selected_footprints = [
f for f in board.GetFootprints() if f.IsSelected()
]
if not selected_footprints:
wx.MessageBox(
"Please select at least one footprint...",
"No Footprints Selected",
wx.OK | wx.ICON_INFORMATION
)
return
# Launch non-modal dialog
PluginDialog(None, selected_footprints)
Overview: Contains
PluginDialog
class inheriting fromwx.Dialog
. Implements:
- UI layout (
InitUI
).- Event handlers for all buttons.
- Filtering and data extraction (
_apply_text_filters
,extract_data
).- Export functions (
generate_markdown
,generate_csv
,save_file_dialog
).
(Full code provided in download section.)
-
Line 1: Import
ExtractPinsPlugin
. - Line 3: Instantiate and register: makes plugin visible to KiCad.
-
Imports:
-
pcbnew
: KiCad PCB API. -
wx
: wxPython. -
os
: file paths. -
PluginDialog
: GUI class.
-
-
**Class **``
-
``:
-
self.name
,self.category
,self.description
: plugin metadata. -
self.show_toolbar_button
: toolbar icon toggle. -
icon_file_name
: path to icon. -
version
: plugin version.
-
-
``:
-
GetBoard()
: current PCB. -
GetFootprints()
,IsSelected()
: filter selected footprints. -
Validation: if empty, show message and
return
. -
Dialog:
PluginDialog(None, selected_footprints)
opens GUI.
-
-
class PluginDialog(wx.Dialog):
"""
Non-modal dialog for pin extraction.
"""
def __init__(self, parent, initial_selected_footprints):
# Call base constructor: set title & size
super().__init__(parent, title="KiCad Pin Extractor", size=(750, 480))
# KiCad board & footprints
self.board = pcbnew.GetBoard()
self.all_board_footprints = self.board.GetFootprints()
# Unique component values
self.all_values = sorted({
fp.GetValue() for fp in self.all_board_footprints if fp.GetValue()
})
# Collect all net names & connector types
all_nets = set(); all_connector_types = set()
for fp in self.all_board_footprints:
for pad in fp.Pads():
net = pad.GetNet()
if net: all_nets.add(net.GetNetname())
val = self._get_footprint_property_safe(fp, "connector-type")
if val: all_connector_types.add(val.strip())
self.all_net_names = sorted(all_nets)
self.all_connector_types = sorted(all_connector_types)
# UI state
self.current_display_footprints = []
self.InitUI()
self._update_footprint_list_display(initial_selected_footprints)
self.Centre(); self.Show()
self.Bind(wx.EVT_CLOSE, self.OnClose)
Explanation:
- Initializes board references and gathers data for filter dropdowns.
- Calls
InitUI()
to build the interface. - Populates the list with
initial_selected_footprints
. - Centers and shows the dialog.
- Binds close event.
Builds the GUI layout in three main sections:
def InitUI(self):
panel = wx.Panel(self)
main_vbox = wx.BoxSizer(wx.VERTICAL)
# Top: List of selected components & details panel
top_hbox = wx.BoxSizer(wx.HORIZONTAL)
# -- Left: Footprint List
list_panel = wx.Panel(panel)
list_vbox = wx.BoxSizer(wx.VERTICAL)
list_vbox.Add(wx.StaticText(list_panel, label="Selected Components:"), 0, wx.ALL, 2)
self.footprint_list_ctrl = wx.ListCtrl(list_panel, size=(-1,120), style=wx.LC_REPORT|wx.LC_NO_HEADER)
# Column definitions
self.footprint_list_ctrl.InsertColumn(0, "Reference")
self.footprint_list_ctrl.SetColumnWidth(0, 150)
self.footprint_list_ctrl.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnListItemSelected)
list_vbox.Add(self.footprint_list_ctrl, 0, wx.EXPAND|wx.ALL, 2)
# -- Selection controls: refresh & remove
selection_hbox = wx.BoxSizer(wx.HORIZONTAL)
self.multi_select_checkbox = wx.CheckBox(list_panel, label="Multi-select from PCB")
selection_hbox.Add(self.multi_select_checkbox, 0, wx.ALL, 2)
refresh_btn = wx.Button(list_panel, label="Refresh Selection")
refresh_btn.Bind(wx.EVT_BUTTON, self.OnRefreshSelection)
selection_hbox.Add(refresh_btn, 0, wx.ALL, 2)
remove_btn = wx.Button(list_panel, label="Remove Selected")
remove_btn.Bind(wx.EVT_BUTTON, self.OnRemoveSelectedFromList)
selection_hbox.Add(remove_btn, 0, wx.ALL, 2)
list_vbox.Add(selection_hbox, 0, wx.EXPAND|wx.ALL, 2)
list_panel.SetSizer(list_vbox)
top_hbox.Add(list_panel, 1, wx.EXPAND|wx.ALL, 2)
# -- Right: Details panel
details_panel = wx.Panel(panel)
details_vbox = wx.BoxSizer(wx.VERTICAL)
details_vbox.Add(wx.StaticText(details_panel, label="Component Details:"), 0, wx.ALL, 2)
self.details_text_ctrl = wx.TextCtrl(details_panel, size=(-1,120), style=wx.TE_MULTILINE|wx.TE_READONLY)
details_vbox.Add(self.details_text_ctrl, 0, wx.EXPAND|wx.ALL, 2)
details_panel.SetSizer(details_vbox)
top_hbox.Add(details_panel, 1, wx.EXPAND|wx.ALL, 2)
main_vbox.Add(top_hbox, 0, wx.EXPAND|wx.ALL, 2)
# Middle: Filters & Options panels
...
# Bottom: Status bar & buttons
...
panel.SetSizer(main_vbox)
main_vbox.Fit(self)
Key UI elements:
- Footprint ListCtrl: shows references.
- Details TextCtrl: displays properties.
- Filter dropdowns: value, net name, connector type.
- Option checkboxes: highlight nets, sort, ignore unconnected.
- Output column checkboxes: choose which columns to include.
- Buttons: Export Selected, Export 'J's, Export by type, Extract Unique Nets, Help, Close.
- Progress bar & status text.
# Retrieves current KiCad selection:
new = [f for f in self.board.GetFootprints() if f.IsSelected()]
if self.multi_select_checkbox.IsChecked():
# Merge with existing list (natural sort)
...
else:
# Replace list
self._update_footprint_list_display(new)
wx.MessageBox(...)
- Multi-select mode: merges new selection with existing.
- Single-select mode: replaces list.
- Gets which item was clicked.
- Calls
_get_footprint_properties_for_display()
to fetch details. - Populates
details_text_ctrl
.
- Identifies highlighted rows in
ListCtrl
. - Removes those footprints from
current_display_footprints
. - Calls
_update_footprint_list_display()
.
- Attempts to open
help_doc.html
in default browser. - Error handling if file missing.
- All funnel into
_process_and_export()
or custom extraction logic:- Apply text filters via
_apply_text_filters()
. - Extract data via
extract_data()
. - Optionally sort references.
- Call
generate_markdown()
andgenerate_csv()
. - Show file dialogs to save.
- Apply text filters via
- Reads value and net name filter inputs.
- Filters footprints accordingly.
- Returns filtered list.
extract_data(self, footprints_to_process, ignore_unconnected_pins_for_csv, ignore_free_pins_for_csv)
- Iterates each footprint:
- Gathers general_properties (ref, value, footprint name, desc, layer, pos, rot, connector type).
- Iterates each pad:
- Records
pad_name
andnet_name
. - Applies pin-level CSV filters.
- Records
- Stores:
-
pin_data
(unfiltered) for Markdown. -
filtered_pins_for_csv
for CSV.
-
- Returns dict keyed by reference.
- Builds Markdown string:
- Header
# Extracted Component Pin Data
. - Loops each component:
- Section
## Component: REF
. - General properties table.
- Pin details table.
- If
apply_highlight
: wraps net names in<span style>
with assigned colors.
- Section
- Header
- Returns finalized Markdown text.
- Uses CSV writer to generate rows:
- For each component, writes
Component: REF
row. - Writes key/value rows for selected general props.
- Writes pin header row:
Connector Name, Pin Number, Net Name
. - Writes each filtered pin row.
- For each component, writes
- Returns CSV string.
- Opens a
wx.FileDialog
(save mode). - Writes
content
to chosen file path. - Shows success or error via
wx.MessageBox
.
-
Filters: add new dropdown/text control in
InitUI()
; extend_apply_text_filters()
. -
Columns: modify
column_checkbox_data
inInitUI()
; adjustselected_columns
mapping. -
Export Formats: tweak
generate_markdown()
&generate_csv()
logic. -
Help Content: edit or replace
help_doc.html
file in plugin directory.