mte.ui — construtores de especificação de formulário¶
Toda superfície de interface da fase 3 — ctx.docks.add_panel e
ctx.settings_page.register — recebe uma
especificação de formulário: um dicionário simples descrevendo uma árvore de
widgets. Construa essas especificações com os auxiliares mte.ui.*, para não
precisar escrever o JSON à mão.
from mte.ui import (
Column, Row, Group,
Label, Button, Checkbox, LineEdit, NumberSpin, ComboBox, List,
)
Nada em mte.ui conversa com o Qt ou o PySide — cada auxiliar devolve um dicionário
seguindo o esquema de canal que o analisador de formulários em C++ do host espera.
Fique à vontade para compô-los, emendar listas ou gerá-los programaticamente:
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)])
A especificação é validada do lado do host; tipos de controle desconhecidos ou
campos obrigatórios ausentes produzem um erro InvalidParams que você verá no log.
Os rótulos de uma especificação de formulário não são traduzidos
Todo rótulo que você põe em uma especificação — títulos de painel, rótulos de
caixas de seleção, títulos de grupo — é exibido exatamente como você o escreveu,
seja qual for o idioma da interface. Eles são dados que o seu plugin envia ao
editor, não cadeias que o editor possa procurar em um catálogo de tradução. Se o
seu plugin deve falar mais de um idioma, escolha as cadeias você mesmo antes de
chamar register; o idioma atual da interface é
ctx.app_settings.get_string(mte.keys.UI_LANGUAGE) (vazio significa "seguir o
sistema"). O mesmo vale para o name e a description que o seu plugin.json
exibe em Preferências ▸ Plug-ins.
Layouts¶
Os construtores de layout recebem uma lista de dicionários filhos e os dispõem vertical ou horizontalmente.
Column(children)¶
Empilha os filhos de cima para baixo com um esticamento ao final — os controles ficam na altura natural deles, em vez de inflarem para preencher um painel alto.
Row(children)¶
Mesma ideia, da esquerda para a direita, com um esticamento horizontal ao final.
Group(children, *, title="")¶
Uma moldura com título (renderizada como QGroupBox) contendo uma pilha vertical.
Use-a para agrupar visualmente controles relacionados:
Group([
Checkbox(id="cs", label="Case sensitive", binds="settings:cs"),
Checkbox(id="ww", label="Whole words", binds="settings:ww"),
], title="Search options")
Os layouts se aninham livremente — uma Row dentro de uma Column dentro de um
Group funciona.
Controles folha¶
Toda folha aceita as mesmas quatro ligações compartilhadas por argumentos nomeados:
| Argumento | Significado |
|---|---|
id= |
Id estável usado por ctx.ui.get / ctx.ui.set e (implicitamente) por binds. |
binds= |
"settings:<key>" — persiste automaticamente por ctx.settings. |
on_click= |
Id de comando a invocar — apenas em Botões. |
on_change= |
Id de manipulador (ctx.docks.on_change(...)) — em todos os outros controles. |
Apenas as folhas que expõem um "valor" suportam binds e on_change.
Label(*, text="", id=None)¶
Texto estático.
Button(*, text, on_click=None, id=None)¶
Um botão. Disparar on_click invoca o comando registrado; se você quiser manter o
botão em sincronia com outra coisa, pode usar ctx.ui.set no text dele.
Checkbox(*, label="", default=False, id=None, binds=None, on_change=None)¶
Controle booleano. default é o estado inicial; binds o substitui pelo valor
persistido, se houver um.
LineEdit(*, placeholder="", default="", id=None, binds=None, on_change=None)¶
Entrada de texto de uma linha.
NumberSpin(*, default=0, min=None, max=None, step=1, id=None, binds=None, on_change=None)¶
Caixa numérica com setas. min e max limitam o intervalo (ambos opcionais; o
QSpinBox subjacente usa o intervalo padrão dele quando não definidos). step é o
incremento das setas.
Intervalo de int
O NumberSpin se apoia no QSpinBox, que armazena um int (32 bits). Valores
fora de -2_147_483_648 … 2_147_483_647 saturam no limite da plataforma.
ComboBox(*, items, default="", id=None, binds=None, on_change=None)¶
Lista suspensa. items é uma lista — cada entrada pode ser uma cadeia simples, ou
um objeto como {"value": "cpp", "label": "C++"} (apenas value é usado hoje;
label está reservado para um refinamento futuro).
List(*, items, id=None, on_change=None)¶
Widget de lista com seleção única. on_change dispara com o texto do item
recém-selecionado. Sem binds — persista a seleção você mesmo se precisar.
Acesso em tempo de execução¶
Uma vez registrado o painel, comande-o a partir de qualquer comando:
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)
Veja ctx.ui para a referência completa.
Persistindo valores¶
binds="settings:<key>" é a forma mais curta de persistir o valor de um
controle:
- Na construção do painel, o widget lê o valor inicial de
ctx.settings.get(key, <default>). - A cada edição do usuário, o widget grava de volta por
ctx.settings.set(chave, novo_valor).
Como painéis e páginas de Preferências compartilham ctx.settings, dois controles
com a mesma cadeia binds se espelham em tempo real. É assim que o painel e a
página de Preferências do HelloPython mantêm a caixa de seleção "Loud" em sincronia.
Se você precisa persistir algo que o vocabulário não cobre (por exemplo, a seleção
de uma List), leia e grave diretamente por ctx.settings em uma retrochamada
on_change.