Zum Inhalt springen

Ein Tool-Plugin schreiben

Dieses Tutorial zeigt, wie Sie ein Python-Tool erstellen, das mit einem automatisch generierten Optionsdialog im Menüsystem von LinkCAD erscheint.

Das Tool-Framework

Ein Tool-Plugin besteht aus:

  1. einer mit @tool() dekorierten Klasse, die Tool erweitert
  2. Option-Klassenattributen, die den UI-Dialog definieren
  3. einer run()-Methode, die die Logik implementiert und ein Ergebnis-Dictionary zurückgibt

Die an run() übergebene drawing ist ein linkcad.v1.db.Drawing — die aktive Datenbank, die der Anwendung gehört. Lesen Sie sie über die Datenbank-API: drawing.cells, drawing.layers, cell.shapes und so weiter.

Beispiel: Ebenenstatistik

Erstellen Sie eine Datei layer_stats.py in Ihrem Plugin-Verzeichnis:

from typing import Any, Dict
from linkcad.v1.plugin import tool, Tool, Option
@tool(
name="Layer Statistics",
menu="Tools/Analysis",
tooltip="Show shape count per layer",
)
class LayerStats(Tool):
include_empty = Option.boolean(
"Include empty layers",
default=False,
tooltip="Show layers with zero shapes",
)
def run(self, drawing) -> Dict[str, Any]:
counts = {layer.name: 0 for layer in drawing.layers}
# One pass over the drawing, sorting each shape into its layer's tally.
# Walking the drawing once per layer would re-read every shape as many
# times as there are layers.
for cell in drawing.cells:
for shape in cell.shapes:
if shape.layer is not None:
counts[shape.layer.name] = counts.get(shape.layer.name, 0) + 1
if not self.include_empty:
counts = {name: n for name, n in counts.items() if n}
return {
"layers": counts,
"summary": f"{len(counts)} layers, {sum(counts.values())} shapes",
}
def format_result(self, result: Dict[str, Any]) -> str:
lines = [f"{name}: {n} shapes" for name, n in result["layers"].items()]
lines += ["", result["summary"]]
return "\n".join(lines)

Funktionsweise

  1. @tool() registriert die Klasse als LinkCAD-Tool
  2. name erscheint im Menü, menu legt den Menüpfad fest
  3. Option.boolean(...) erzeugt ein Kontrollkästchen im automatisch generierten Dialog
  4. run() wird aufgerufen, wenn der Benutzer im Dialog auf OK klickt, und gibt ein Ergebnis-Dictionary zurück
  5. format_result() wandelt dieses Dictionary in den Text um, den LinkCAD anzeigt. Überschreiben Sie es für alles, was schöner sein soll als die Standardausgabe

Die Zeichnung ändern

Während run() läuft, hält das Framework eine Lesesperre. Zum Schreiben öffnen Sie eine Transaktion — sie wird bei Erfolg bestätigt, bei einer Ausnahme zurückgerollt und bildet einen einzigen Eintrag im Rückgängig-Verlauf:

from linkcad.v1.db import Transaction
def run(self, drawing):
with Transaction(drawing, "Add Frame"):
frame = drawing.add_cell("FRAME")
layer = drawing.add_layer("OUTLINE")
b = drawing.main_cell.bounds
frame.add_polyline(
layer,
[(b.min_x, b.min_y), (b.max_x, b.min_y),
(b.max_x, b.max_y), (b.min_x, b.max_y)],
closed=True,
)
return {"summary": "Added FRAME"}

Optionstypen

FactoryUI-ElementBeispiel
Option.integer()DrehfeldOption.integer("Count", default=1, min=0, max=100)
Option.real()Dezimal-DrehfeldOption.real("Scale", default=1.0, decimals=4)
Option.boolean()KontrollkästchenOption.boolean("Enable", default=True)
Option.string()TextfeldOption.string("Name", default="output")
Option.choice()AuswahllisteOption.choice("Mode", choices=["Fast", "Precise"])
Option.path()DateiauswahlOption.path("Output", file_filter="*.csv")
Option.color()FarbauswahlOption.color("Fill", default="#FF0000")
Option.table()Editierbares RasterSiehe Panel-Zusammenstellung
Option.cell_choice()Zellen-AuswahllisteOption.cell_choice("Target Cell")

Bedingte Optionen

Mit enabled_when lassen sich Optionen dynamisch aktivieren und deaktivieren:

class MyTool(Tool):
mode = Option.choice("Mode", choices=["Simple", "Advanced"])
threshold = Option.real(
"Threshold",
default=0.5,
enabled_when=lambda self: self.mode == "Advanced",
)

Das Feld threshold ist nur aktiv, wenn mode auf „Advanced“ steht.

Tastenkürzel

@tool(
name="My Tool",
menu="Tools/Custom",
shortcut="Ctrl+Shift+M",
)
class MyTool(Tool):
...

Nächste Schritte