KiCad Pin Extraction Plugin: Developer Documentation - wayri/KiCAD_Plugins_Wayri GitHub Wiki

KiCad Pin Extraction Plugin - Complete Documentation

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.


Contents

  1. Purpose & Features
  2. Diagrams
  3. Source Code Files
  4. Line-by-Line Explanation
  5. Customization & Extension
  6. Downloadable Markdown

Purpose & Features

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.

Diagrams

1. User Flow

User Flow

  1. User selects footprints in KiCad PCB editor.
  2. Launch plugin via Tools โ†’ External Plugins or toolbar button.
  3. PluginDialog appears.
  4. User applies filters, views details, and clicks export.
  5. Plugin saves .md, .csv

2. Program Structure

Below is an overview of how the pluginโ€™s modules interact: Program Structure

__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

๐Ÿ“‚ Source Code Files

1. __init__.py

# Registers the plugin on import
from .extract_pins_plugin import ExtractPinsPlugin

# Instantiate and register with KiCad
ExtractPinsPlugin().register()

2. extract_pins_plugin.py

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)

3. plugin_dialog.py

Overview: Contains PluginDialog class inheriting from wx.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-by-Line Explanation

A. __init__.py

  • Line 1: Import ExtractPinsPlugin.
  • Line 3: Instantiate and register: makes plugin visible to KiCad.

B. extract_pins_plugin.py

  1. Imports:

    • pcbnew: KiCad PCB API.
    • wx: wxPython.
    • os: file paths.
    • PluginDialog: GUI class.
  2. **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.

C. plugin_dialog.py

1. Class Definition & Initialization

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.

2. InitUI()

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.

3. Event Handlers

OnRefreshSelection(self, event)
# 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.
OnListItemSelected(self, event)
  • Gets which item was clicked.
  • Calls _get_footprint_properties_for_display() to fetch details.
  • Populates details_text_ctrl.
OnRemoveSelectedFromList(self, event)
  • Identifies highlighted rows in ListCtrl.
  • Removes those footprints from current_display_footprints.
  • Calls _update_footprint_list_display().
OnHelp(self, event)
  • Attempts to open help_doc.html in default browser.
  • Error handling if file missing.
OnExportSelected, OnExportJs, OnExportConnectorsByType, OnExtractUniqueNets
  • 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() and generate_csv().
    • Show file dialogs to save.

4. Filtering & Data Extraction

_apply_text_filters(self, footprints_list)
  • 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 and net_name.
      • Applies pin-level CSV filters.
    • Stores:
      • pin_data (unfiltered) for Markdown.
      • filtered_pins_for_csv for CSV.
  • Returns dict keyed by reference.

5. Export Logic

generate_markdown(self, data_by_footprint, apply_highlight, selected_columns)
  • 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.
  • Returns finalized Markdown text.
generate_csv(self, data_by_footprint, selected_columns)
  • 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.
  • Returns CSV string.
save_file_dialog(self, content, wildcard, title, default_filename)
  • Opens a wx.FileDialog (save mode).
  • Writes content to chosen file path.
  • Shows success or error via wx.MessageBox.

Customization & Extension

  • Filters: add new dropdown/text control in InitUI(); extend _apply_text_filters().
  • Columns: modify column_checkbox_data in InitUI(); adjust selected_columns mapping.
  • Export Formats: tweak generate_markdown() & generate_csv() logic.
  • Help Content: edit or replace help_doc.html file in plugin directory.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ