Zum Inhalt

mte.ui — Formular-Spezifikations-Builder

Jede UI-Fläche der Phase 3 — ctx.docks.add_panel und ctx.settings_page.register — nimmt eine Formular-Spezifikation: ein einfaches Dict, das einen Widget-Baum beschreibt. Bauen Sie diese Spezifikationen mit den mte.ui.*-Helfern, damit Sie das JSON nicht von Hand schreiben müssen.

from mte.ui import (
    Column, Row, Group,
    Label, Button, Checkbox, LineEdit, NumberSpin, ComboBox, List,
)

Nichts in mte.ui spricht mit Qt oder PySide — jeder Helfer liefert ein Dict nach dem Wire-Schema, das der C++-Formularparser des Hosts erwartet. Komponieren Sie sie frei, verketten Sie Listen oder erzeugen Sie sie programmatisch:

from mte.ui import Column, Row, Label, Button

def make_toolbar(commands):
    return Row([Button(text=c["label"], on_click=c["id"])
                for c in commands])

form = Column([Label(text="Actions:"),
               make_toolbar(my_commands)])

Die Spezifikation wird hostseitig validiert; unbekannte Steuerelementtypen oder fehlende Pflichtfelder erzeugen einen InvalidParams-Fehler, den Sie im Protokoll sehen.

Die Beschriftungen in einer Formularspezifikation werden nicht übersetzt

Jede Beschriftung in einer Spezifikation — Panel-Titel, Checkbox-Labels, Gruppenüberschriften — wird genau so angezeigt, wie Sie sie geschrieben haben, unabhängig von der Sprache der Benutzeroberfläche. Es sind Daten, die Ihr Plugin an den Editor sendet, keine Strings, die der Editor in einem Übersetzungskatalog nachschlagen könnte. Soll Ihr Plugin mehrere Sprachen sprechen, wählen Sie die Strings selbst, bevor Sie register aufrufen; die aktuelle Sprache liefert ctx.app_settings.get_string(mte.keys.UI_LANGUAGE) (leer bedeutet „dem System folgen"). Dasselbe gilt für name und description aus Ihrer plugin.json, die unter Einstellungen ▸ Erweiterungen erscheinen.


Layouts

Layout-Builder nehmen eine Liste von Kind-Dicts und ordnen sie vertikal oder horizontal an.

Column(children)

Stapelt Kinder von oben nach unten mit abschließender Dehnung — Steuerelemente behalten ihre natürliche Höhe, statt sich in einem hohen Dock aufzublähen.

Row(children)

Dieselbe Idee, von links nach rechts, mit abschließender horizontaler Dehnung.

Group(children, *, title="")

Ein betitelter Rahmen (gerendert als QGroupBox) mit vertikalem Stapel. Nutzen Sie ihn, um zusammengehörige Steuerelemente visuell zu gruppieren:

Group([
    Checkbox(id="cs", label="Case sensitive", binds="settings:cs"),
    Checkbox(id="ww", label="Whole words",    binds="settings:ww"),
], title="Search options")

Layouts verschachteln frei — eine Row in einer Column in einer Group ist in Ordnung.


Blatt-Steuerelemente

Jedes Blatt akzeptiert dieselben vier gemeinsamen Bindungen als Schlüsselwortargumente:

Argument Bedeutung
id= Stabile Id für ctx.ui.get / ctx.ui.set und (implizit) binds.
binds= "settings:<key>" — automatische Persistenz über ctx.settings.
on_click= Aufzurufende Befehls-Id — nur Buttons.
on_change= Handler-Id (ctx.docks.on_change(...)) — jedes andere Steuerelement.

Nur Blätter mit einem „Wert“ unterstützen binds und on_change.

Label(*, text="", id=None)

Statischer Text.

Button(*, text, on_click=None, id=None)

Eine Schaltfläche. Das Auslösen von on_click ruft den registrierten Befehl auf; wollen Sie die Schaltfläche mit etwas anderem synchron halten, können Sie ihren text per ctx.ui.set setzen.

Checkbox(*, label="", default=False, id=None, binds=None, on_change=None)

Boolesches Steuerelement. default ist der Anfangszustand; binds übersteuert ihn mit dem persistierten Wert, falls einer existiert.

LineEdit(*, placeholder="", default="", id=None, binds=None, on_change=None)

Einzeiliges Texteingabefeld.

NumberSpin(*, default=0, min=None, max=None, step=1, id=None, binds=None, on_change=None)

Ganzzahl-Spinbox. min und max begrenzen den Bereich (beide optional; die zugrundeliegende QSpinBox nutzt ihren Standardbereich, wenn ungesetzt). step ist das Inkrement der Pfeile.

int-Bereich

NumberSpin basiert auf QSpinBox, die einen int (32-Bit) speichert. Werte außerhalb von -2_147_483_648 … 2_147_483_647 sättigen am Plattformlimit.

ComboBox(*, items, default="", id=None, binds=None, on_change=None)

Dropdown. items ist eine Liste — jeder Eintrag darf eine einfache Zeichenkette sein oder ein Objekt wie {"value": "cpp", "label": "C++"} (heute wird nur value genutzt; label ist für eine spätere Verfeinerung reserviert).

List(*, items, id=None, on_change=None)

Listen-Widget mit Einzelauswahl. on_change feuert mit dem Text des neu gewählten Eintrags. Kein binds — persistieren Sie die Auswahl bei Bedarf selbst.


Zugriff zur Laufzeit

Sobald das Panel registriert ist, steuern Sie es aus jedem Befehl:

panel_id = ctx.docks.add_panel(id="my.panel", ..., form=Column([
    LineEdit(id="needle"),
    Checkbox(id="cs"),
]))

# Read current values
needle = ctx.ui.get(panel_id, "needle")
cs     = ctx.ui.get(panel_id, "cs") == "true"

# Write values (does NOT fire on_change)
ctx.ui.set(panel_id, "needle", "hello")
ctx.ui.set(panel_id, "cs", True)

Die vollständige Referenz: ctx.ui.


Werte persistieren

binds="settings:<key>" ist der kürzeste Weg, den Wert eines Steuerelements zu persistieren:

  • Beim Aufbau des Panels liest das Widget seinen Anfangswert aus ctx.settings.get(key, <default>).
  • Bei jeder Benutzeränderung schreibt das Widget über ctx.settings.set(schlüssel, neuer_wert) zurück.

Da Panels und Einstellungsseiten ctx.settings teilen, spiegeln sich zwei Steuerelemente mit derselben binds-Zeichenkette in Echtzeit. Genau so halten HelloPythons Dock und Einstellungsseite das „Loud“-Kästchen synchron.

Müssen Sie etwas persistieren, das das Vokabular nicht abdeckt (z. B. eine List-Auswahl), lesen/schreiben Sie direkt über ctx.settings in einem on_change-Callback.