Aller au contenu

mte.ui — constructeurs de spécifications de formulaires

Chaque surface d'interface de la phase 3 — ctx.docks.add_panel et ctx.settings_page.register — prend une spécification de formulaire : un simple dict décrivant un arbre de widgets. Construisez ces spécifications avec les aides mte.ui.* pour ne pas écrire le JSON à la main.

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

Rien dans mte.ui ne parle à Qt ni à PySide — chaque aide renvoie un dict suivant le schéma de fil attendu par l'analyseur de formulaires C++ de l'hôte. Composez-les librement, épissez des listes ou générez-les par programme :

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)])

La spécification est validée côté hôte ; les types de contrôles inconnus ou les champs requis manquants produisent une erreur InvalidParams visible dans le journal.


Mises en page

Les constructeurs de mise en page prennent une liste de dicts enfants et les disposent verticalement ou horizontalement.

Column(children)

Empile les enfants de haut en bas avec un étirement final — les contrôles gardent leur hauteur naturelle au lieu de gonfler pour remplir un dock haut.

Row(children)

Même idée, de gauche à droite, avec un étirement horizontal final.

Group(children, *, title="")

Un cadre titré (rendu en QGroupBox) contenant une pile verticale. À utiliser pour grouper visuellement des contrôles liés :

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

Les mises en page s'imbriquent librement — une Row dans une Column dans un Group ne pose aucun problème.


Contrôles feuilles

Chaque feuille accepte les quatre mêmes liaisons partagées via arguments nommés :

Argument Signification
id= Id stable utilisé par ctx.ui.get / ctx.ui.set et (implicitement) binds.
binds= "settings:<clé>" — persistance automatique via ctx.settings.
on_click= Id de commande à invoquer — Buttons uniquement.
on_change= Id de gestionnaire (ctx.docks.on_change(...)) — tout autre contrôle.

Seules les feuilles exposant une « valeur » prennent en charge binds et on_change.

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

Texte statique.

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

Un bouton. Déclencher on_click invoque la commande enregistrée ; pour garder le bouton synchronisé avec autre chose, vous pouvez ctx.ui.set son text.

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

Contrôle booléen. default est l'état initial ; binds le remplace par la valeur persistée si elle existe.

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

Saisie de texte sur une ligne.

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

Compteur d'entiers. min et max bornent la plage (tous deux facultatifs ; la QSpinBox sous-jacente garde sa plage par défaut sinon). step est l'incrément des flèches.

Plage des int

NumberSpin s'appuie sur QSpinBox, qui stocke un int (32 bits). Les valeurs hors de -2_147_483_648 … 2_147_483_647 saturent à la limite de la plateforme.

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

Liste déroulante. items est une liste — chaque entrée peut être une simple chaîne, ou un objet comme {"value": "cpp", "label": "C++"} (seul value est utilisé aujourd'hui ; label est réservé à un raffinement futur).

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

Widget de liste à sélection unique. on_change se déclenche avec le texte de l'élément nouvellement sélectionné. Pas de binds — persistez la sélection vous-même si nécessaire.


Accès à l'exécution

Une fois le panneau enregistré, pilotez-le depuis n'importe quelle commande :

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)

Voir ctx.ui pour la référence complète.


Persister les valeurs

binds="settings:<clé>" est le chemin le plus court pour persister la valeur d'un contrôle :

  • À la construction du panneau, le widget lit sa valeur initiale depuis ctx.settings.get(clé, <default>).
  • À chaque modification de l'utilisateur, le widget réécrit via ctx.settings.set(clé, nouvelle_valeur).

Comme les panneaux et les pages de Préférences partagent ctx.settings, deux contrôles avec la même chaîne binds se reflètent en temps réel. C'est ainsi que le dock de HelloPython et sa page de Préférences gardent la case « Loud » synchronisée.

Si vous devez persister quelque chose que le vocabulaire ne couvre pas (p. ex. une sélection de List), lisez/écrivez directement via ctx.settings dans un rappel on_change.