Skip to content
ispyisail edited this page Oct 9, 2026 · 9 revisions

Automating QElectroTech

How to drive QET from other programs, and what the XML files look like.

Correction, September 2026. Earlier versions of this page stated that QElectroTech supports Python scripting and a plugin system, and told readers to install plugins into ~/.local/share/QElectroTech/plugins/ and equivalents. None of that exists. There is no embedded interpreter, no plugin interface, and no plugin directory β€” QET never reads those paths. The page below describes what is actually there, which is a good deal, just not that.

What QET actually offers:

A headless command line 14 verbs that open a project and export, inspect or rewrite it without a GUI.
JavaScript scripting --run script.js project.qet, or Run a script... in the editor β€” read the model, export, edit with real undo. See JavaScript Scripting.
An AI-assistant server misc/qet-mcp/qet_mcp.py, which lets Claude, Copilot and others read, check and edit projects through that scripting engine. See MCP server.
XML files .qet and .elmt are plain XML you can read and write with any tool.
An external companion program qet_tb_generator, launched from a menu entry.
C++ source For anyone building QET itself, or a fork.

What it still does not offer: a plugin API or a loadable-module directory. The JavaScript engine above is explicit, one-shot script execution, not a plugin system β€” nothing runs unless you tell it to. The one way into an already-running QElectroTech is live mode: off by default, confirmed at start, local to your computer, and limited to running scripts and a fixed list of commands, each one undoable.


1. The command line

This is the part most automation should use. A recognised export flag is detected before the GUI starts, so the process runs headless, does the work and exits β€” it does not open a window and does not hand off to an already-running instance.

qelectrotech --export-pdf myproject.qet out.pdf

Arguments are positional, not --flag=value. The shape is always qelectrotech <flag> <project.qet> <output>, with two exceptions noted below.

The verbs

Flag Output Notes
--export-pdf one PDF all sheets, one page each
--export-png a directory one NN_Title.png per sheet
--export-svg a directory one NN_Title.svg per sheet
--export-dxf a directory one DXF per sheet; see DXF import & export
--export-bom CSV bill of materials, from the project database β€” same source as the GUI export
--export-wiring CSV from-to wiring list, one row per conductor β€” same as menu Project β†’ Wiring list (database) / Export the wiring plan
--export-cables CSV the same logical list, built from the document XML instead
--export-wires CSV conductor numbers β€” same as menu Project β†’ Export the list of conductor names
--export-nets CSV electrical nets β€” terminals grouped into potentials
--export-links CSV cross-references, flagging masters and slaves with no link
--info JSON structural dump: per-sheet element and conductor counts, unconnected terminals. Writes to stdout if no output path is given
--resave .qet loads and writes the XML back out
--set-titleblock .qet stamps title-block fields, then saves
--check-elements report validates .elmt files β€” takes a file or directory, not a project

Two extra switches:

  • --show-terminals β€” paint terminal markers and names into PDF/PNG/SVG output. Off by default, which matches the GUI export dialog. Useful for visually debugging an unconnected pin.
  • --set-titleblock takes trailing key=value assignments after the output path: date=today or an ISO YYYY-MM-DD date, standard title-block keys, or any other key, which is stored as a custom field. Bad assignments fail before anything is written.

Environment variables

Variable Effect
QET_ENABLE_SCRIPTING=1 lets --run run a script without the setting being ticked, for CI and batch jobs (see JavaScript Scripting)
QET_SETTINGS_DIR=<folder> keeps QElectroTech's settings in <folder>/QElectroTech/QElectroTech.ini instead of the registry (Windows), the system preferences (macOS) or ~/.config (Linux). Give each job its own folder and it can neither read nor change your own settings, on every system
QT_QPA_PLATFORM=offscreen runs without a display (see below)

QET_SETTINGS_DIR came from issue #1178 (PRs #1183, #1254 for macOS). To point a headless run at a symbol collection, write the folder into that INI file first:

[elements-collections]
common-collection-path=/path/to/qelectrotech/elements

Exit codes

0 success Β· 1 the work failed (project would not open, nothing to export, file not writable) Β· 2 you called it wrong (missing argument, bad assignment). That makes it safe to use in a CI pipeline directly.

Worth knowing

  • --export-cables and --export-wiring are meant to agree. One is built from the document XML, the other from the project database. Running both and diffing them is a direct check that the database still describes the project β€” something otherwise only observable through the GUI.
  • Always pass a timeout in scripts. A project saved by an older QET raises a version warning on load; CLI mode answers message boxes instead of showing them, but an unexpected modal is the classic way to hang a headless run forever.
  • Crash-recovery backups are disabled in CLI mode on purpose β€” the background backup write races process exit.
  • QT_QPA_PLATFORM=offscreen is enough for these verbs. No Xvfb is required.
  • This is also QET's real answer to "print wire labels." There is no built-in wire-marker/ferrule label printer in QET (see the User Manual's Printing Diagrams section for what printing does cover). The documented forum workflow is to export this CSV and feed it into a label printer's own software β€” Brady, WAGO Smart-Printer and Phoenix Contact's tools all accept CSV directly. A known limitation, reported by a panel builder on the forum: the export is one row per conductor with no quantity consolidation, so N identical labels come out as N duplicate rows rather than one row with a quantity column β€” expect to de-duplicate in a spreadsheet before printing a large batch. Cembre-style printers that need a .FNR file or support-code column aren't produced by this export at all; that mapping has to be built by hand from the CSV.

Example: a revision pipeline

set -e
qelectrotech --set-titleblock in.qet stamped.qet indexrev=C date=today
qelectrotech --export-pdf stamped.qet "release/rev-C.pdf"
qelectrotech --export-bom stamped.qet "release/rev-C-bom.csv"

See also the CLI Reference.


2. Reading and writing the files directly

.qet and .elmt are XML. Anything that can parse XML can process them β€” Python's xml.etree, lxml, xmlstarlet, XSLT, whatever you like. This is what people mean when they say they "script QET": the script is an ordinary program of your own that reads and writes the files, run alongside QET rather than inside it.

A real .qet skeleton

<project title="ArduinoLCD" version="0.80">
    <properties>
        <property show="1" name="saveddate">17/04/2021</property>
    </properties>
    <newdiagrams>
        <border rows="8" cols="17" rowsize="80" colsize="60" .../>
        <inset folio="%id/%total" author="" title="" .../>
        <conductors type="multi" .../>
        <report label="%f-%l%c"/>
        <xrefs>
            <xref type="coil" master_label="%f-%l%c" slave_label="(%f-%l%c)" .../>
        </xrefs>
    </newdiagrams>
    <diagram title="LCD 4 DATA" order="1" folio="%id/%total" cols="11" rows="7" ...>
        <elements>
            <element x="390" y="570" z="10" orientation="0"
                     type="embed://import/oznaczenia/tekst_08.elmt"
                     uuid="{52d4b9e8-05c3-49a2-8455-a42ff651200a}"
                     prefix="" freezeLabel="false">
                ...
            </element>
        </elements>
        <conductors> ... </conductors>
    </diagram>
    <collection> ... </collection>
</project>

Points that trip people up:

  • There is no <diagrams> wrapper. <diagram> elements are direct children of <project>, one per sheet, ordered by their order attribute.
  • <element> has no id. It is identified by uuid, and its type attribute is a location, usually embed://… for an element copied into the project's own collection.
  • <newdiagrams> holds the defaults for new sheets, not the sheets themselves.
  • Project-wide element definitions live under <collection>, so a project is usually self-contained.

Full reference: Project XML.

A real .elmt skeleton

<definition version="0.90" type="element" link_type="master"
            width="200" height="70" hotspot_x="100" hotspot_y="35">
    <uuid uuid="{2cbd2b72-1d04-f03d-758f-ce3a14dbb3c5}"/>
    <names>
        <name lang="en">UPS</name>
        <name lang="fr">UPS</name>
    </names>
    <kindInformations>
        <kindInformation name="type">coil</kindInformation>
    </kindInformations>
    <informations>Author: RDS for QElectroTech</informations>
    <description>
        <rect x="0" y="0" width="460" height="590" style="..."/>
        <terminal uuid="{73279019-…}" name="" x="-90" y="10" orientation="w" type="Generic"/>
    </description>
</definition>

Points that trip people up:

  • width, height, hotspot_x, hotspot_y are required attributes of <definition>, and width/height must be multiples of 10 β€” QET rounds them up otherwise.
  • The uuid is an attribute (<uuid uuid="{…}"/>), not element text.
  • <name> entries are per-language and need a lang attribute.
  • link_type is what makes an element a master, slave or terminal β€” see Linking elements.

Full reference: Elements XML.

Validate what you generate

Nothing checks a hand-written file until QET opens it, but the CLI will check element files for you:

qelectrotech --check-elements my_elements/

It reports each file as OK, WARN (loads but suspicious β€” for instance zero terminals) or FAIL (unparseable, wrong root tag, missing bounding box), and exits non-zero on any failure. Put it in CI if you generate .elmt files.

It also checks terminal names, with the same rule the element editor applies on save (see Using the element editor Β§5): two terminals of one element sharing a name is a FAIL, and terminals without a name are a WARN (sheet reports, conductor definitions and thumbnails excepted). The element editor's setting to turn the check off does not apply here.

FAIL  my_elements/shelly_pro_2pm.elmt  (repeated terminal names: N Γ—3)
WARN  my_elements/90-10-0111.elmt  (2 of 2 terminals have no name)

Rules of thumb

  • Close the project in QET before rewriting its file. QET holds its own in-memory model and will overwrite you on save.
  • --resave is a cheap normaliser: load and write back, then diff, to see what QET silently rewrites before you build a tool on an assumption about the markup.
  • Element and conductor identity is by UUID. Copying an element node without giving it a fresh uuid produces two elements that QET considers the same one.

3. qet_tb_generator β€” what "plugin" means in QET

There is one menu entry, Launch the terminal block creation plugin, and one program behind it. qet_tb_generator is a separate third-party program, distributed on PyPI, that reads and writes .qet files from the outside to build terminal strips.

python -m pip install --upgrade qet_tb_generator

QET launches it by searching a fixed list of locations β€” QETApp::dataDir() + "/binary/", the current directory, ~/.qet/, and then whatever PATH resolves β€” and starting it as an ordinary child process. That is the entire integration: no shared memory, no API, no callbacks. If the executable is not on one of those paths, the menu entry cannot find it.

Community support lives on the forum: Scripts Β· Code/Programming

Writing "a plugin" therefore means writing a standalone program that manipulates the files, exactly as Β§2 describes. There is no interface to implement and no directory to install into.


4. The C++ source

For changing QET itself, or building a fork:

Orientation points, all in sources/:

Class File Role
QETProject qetproject.cpp a project: sheets, collection, load and save
Diagram diagram.cpp one sheet (a QGraphicsScene)
Element qetgraphicsitem/element.cpp a placed symbol
Conductor qetgraphicsitem/conductor.cpp a wire
Terminal qetgraphicsitem/terminal.cpp a connection point
projectDataBase dataBase/projectdatabase.cpp the query cache β€” see The project database

Note the vocabulary gap: the UI says wire, page and symbol; the code says conductor, diagram and element. Grepping for the UI word is the usual way to conclude wrongly that something is not implemented.


5. Things that do not exist

Stated plainly, because this page previously claimed otherwise:

Claim Reality
Embedded Python scripting Still no Python interpreter. Every Python reference in the source is the qet_tb_generator launcher.
A plugin system / plugin interface Still no QPluginLoader, no plugin ABI, nothing that loads external code, and no directory a project or a third party can drop code into.
An automation API into a running instance Only live mode, for an AI assistant: off by default, a warning at start, a local socket readable only by you, and every action undoable. Otherwise SingleApplication forwards file arguments to a running instance; that is all.

One thing that changed: QET now has an embedded JavaScript engine (QJSEngine, not Python) for explicit, one-shot script runs β€” --run script.js project.qet, or "Run Script..." in the GUI. Not a plugin system: nothing runs automatically, no project file can carry or trigger a script, and it only reads/exports/edits through a narrow, named API, not arbitrary code against QET's internals. See JavaScript Scripting for what it actually does.

Getting Started

Home

🌐 Languages β€” English Β· FranΓ§ais Β· Deutsch

Downloads

Windows without admin rights β€” the portable archive, no installer

Quick Start Guide

User Manual

FAQ

Tips & Tricks

Guides

Conductors β€” wire properties, what feeds which export, cables, and hops where wires cross

Wires per terminal β€” limit the wires on a terminal, chain wiring instead of stars

Printing and exporting β€” paper, PDF, images, and what each path does differently

Linking elements β€” master, slave, terminal

PLC modules β€” I/O tables and linking a wire to a specific point

Using the element editor β€” drawing tools, saving, checks

Grid size and element size β€” why symbols aren't all the same scale, and scaling one without leaving the grid

Preferences reference β€” what each settings page does

Saving and loading settings β€” your whole setup in one file, to copy or keep

Keyboard-only control β€” mouseless QET, and what still needs a mouse

Mouse modifiers β€” what Shift, Ctrl and Alt change while you drag

3D mouse β€” SpaceMouse pan, zoom and buttons

Aligning items β€” snap symbols back to the grid, or line them up

Pictures on a sheet β€” labels, crop, transparency, what they cost in the file

Arcs and curved wires β€” the Arc tool, pulling an arc in or out, rounding a corner with a fillet, dashed arcs for lighting layouts

Grouping items β€” select, move and copy several items as one

Finding your place on a sheet β€” go to a cell like B13 or 4-B7, keep the headers in sight, show the cell limits, zoom and pan

Showing and hiding kinds of items β€” hide texts, wire numbers, shapes, pictures, tables or cross-references on every sheet

Drawing faster β€” place without dragging, the S shortcut bar, command search, gestures

Customising QElectroTech β€” keys, toolbar size and contents, the gesture ring (partly pending)

Managing collections β€” folders, writability, building your own shortlist

Templates β€” reusable multi-element blocks, placed by double-click or drag

Search & Replace β€” bulk property changes

Building a nomenclature query β€” the BOM/summary table builder

Linking wires across pages β€” sheet reports

Variables & formulas β€” %f, %{label}, sequences

Auto-numbering β€” schemes, sequences, freezing

Terminal strips β€” strips, levels, bridges

Title block templates β€” the .titleblock format

Importing EPLAN parts (.edz) β€” EPLAN Data Portal

DXF import & export β€” two unrelated features, one format; command-line export and layers

The project database β€” the in-memory SQLite cache

File formats
Elements XML
Project XML
Development

Building from Source

Contributing Code

Automating QET β€” CLI, XML formats, external tools

CLI Reference β€” command line usage

JavaScript Scripting β€” --run, geometry editing, undo

MCP server β€” let an AI assistant read, verify and edit projects

Connecting an AI assistant β€” setup for Claude, Copilot, Gemini, Codex, Cursor, LM Studio

Script buttons β€” stored scripts with an icon, by hand or by an assistant

Live mode β€” an assistant working in the open project while you watch

Macro recorder β€” record a task by hand, for an assistant to script

Development Roadmap

Vision β€” proposal, under discussion

Developer Tools

About

Features

History

Community

License

Contributing to this Wiki

Clone this wiki locally