mte.ui — costruttori di specifiche di modulo¶
Ogni superficie dell'interfaccia della fase 3 —
ctx.docks.add_panel e
ctx.settings_page.register — accetta una
specifica di modulo: un semplice dizionario che descrive un albero di widget.
Costruisci queste specifiche con gli ausili mte.ui.*, così da non dover
scrivere il JSON a mano.
from mte.ui import (
Column, Row, Group,
Label, Button, Checkbox, LineEdit, NumberSpin, ComboBox, List,
)
Niente in mte.ui parla con Qt o PySide: ogni ausilio restituisce un dizionario
che segue lo schema di trasmissione atteso dall'analizzatore di moduli C++
dell'host. Sentiti libero di comporli, di innestare elenchi o di generarli in
modo programmatico:
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 specifica viene validata lato host; tipi di controllo sconosciuti o campi
obbligatori mancanti producono un errore InvalidParams che vedrai nel log.
Le etichette in una specifica di modulo non vengono tradotte
Ogni didascalia che metti in una specifica — titoli di pannello, etichette di
caselle di spunta, intestazioni di gruppo — viene mostrata esattamente come
l'hai scritta, qualunque sia la lingua dell'interfaccia. Sono dati che il tuo
plugin invia all'editor, non stringhe che l'editor possa cercare in un
catalogo di traduzione. Se il tuo plugin deve parlare più di una lingua,
scegli tu le stringhe prima di chiamare register; la lingua dell'interfaccia
corrente è ctx.app_settings.get_string(mte.keys.UI_LANGUAGE) (vuota
significa «segui il sistema»). Lo stesso vale per il name e la
description che il tuo plugin.json mostra in Preferenze ▸ Estensioni.
Disposizioni¶
I costruttori di disposizione prendono un elenco di dizionari figli e li dispongono verticalmente od orizzontalmente.
Column(children)¶
Impila i figli dall'alto verso il basso con un allungamento finale: i controlli restano alla loro altezza naturale invece di gonfiarsi per riempire un pannello alto.
Row(children)¶
Stessa idea, da sinistra a destra, con un allungamento orizzontale finale.
Group(children, *, title="")¶
Una cornice con titolo (resa come QGroupBox) che contiene una pila verticale.
Usala per raggruppare visivamente controlli correlati:
Group([
Checkbox(id="cs", label="Case sensitive", binds="settings:cs"),
Checkbox(id="ww", label="Whole words", binds="settings:ww"),
], title="Search options")
Le disposizioni si annidano liberamente: una Row dentro una Column dentro un
Group va benissimo.
Controlli foglia¶
Ogni foglia accetta gli stessi quattro collegamenti condivisi tramite argomenti nominati:
| Argomento | Significato |
|---|---|
id= |
Id stabile usato da ctx.ui.get / ctx.ui.set e (implicitamente) da binds. |
binds= |
"settings:<key>" — rende persistente automaticamente tramite ctx.settings. |
on_click= |
Id del comando da invocare — solo per i Button. |
on_change= |
Id del gestore (ctx.docks.on_change(...)) — per ogni altro controllo. |
Solo le foglie che espongono un «valore» supportano binds e on_change.
Label(*, text="", id=None)¶
Testo statico.
Button(*, text, on_click=None, id=None)¶
Un pulsante. Far scattare on_click invoca il comando registrato; se vuoi tenere
il pulsante sincronizzato con qualcos'altro puoi impostarne il text con
ctx.ui.set.
Checkbox(*, label="", default=False, id=None, binds=None, on_change=None)¶
Controllo booleano. default è lo stato iniziale; binds lo scavalca con il
valore reso persistente, se ne esiste uno.
LineEdit(*, placeholder="", default="", id=None, binds=None, on_change=None)¶
Immissione di testo su una sola riga.
NumberSpin(*, default=0, min=None, max=None, step=1, id=None, binds=None, on_change=None)¶
Casella numerica con frecce. min e max limitano l'intervallo (entrambi
facoltativi; il QSpinBox sottostante usa il proprio intervallo predefinito
quando non sono impostati). step è l'incremento sulle frecce.
intervallo di int
NumberSpin si appoggia a QSpinBox, che memorizza un int (a 32 bit). I
valori fuori da -2_147_483_648 … 2_147_483_647 si saturano al limite della
piattaforma.
ComboBox(*, items, default="", id=None, binds=None, on_change=None)¶
Elenco a discesa. items è un elenco: ogni voce può essere una semplice stringa
oppure un oggetto come {"value": "cpp", "label": "C++"} (oggi viene usato solo
value; label è riservato a un perfezionamento futuro).
List(*, items, id=None, on_change=None)¶
Widget elenco a selezione singola. on_change scatta con il testo della voce
appena selezionata. Nessun binds: se ti serve, rendi persistente la selezione
da te.
Accesso a tempo di esecuzione¶
Una volta registrato il pannello, pilotalo da un comando qualsiasi:
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)
Vedi ctx.ui per la documentazione completa.
Rendere persistenti i valori¶
binds="settings:<key>" è il modo più breve per rendere persistente il valore di
un controllo:
- Alla costruzione del pannello, il widget legge il proprio valore iniziale da
ctx.settings.get(key, <default>). - A ogni modifica dell'utente, il widget riscrive tramite
ctx.settings.set(key, new_value).
Poiché sia i pannelli sia le pagine delle Preferenze condividono ctx.settings,
due controlli con la stessa stringa binds si rispecchiano a vicenda in tempo
reale. È così che il pannello e la pagina delle Preferenze di HelloPython tengono
sincronizzata la casella «Loud».
Se devi rendere persistente qualcosa che il vocabolario non copre (per esempio la
selezione di una List), leggi e scrivi direttamente tramite ctx.settings in
una callback on_change.