Přeskočit obsah

mte.ui — stavitelé specifikací formulářů

Každá plocha rozhraní z fáze 3 — ctx.docks.add_panel a ctx.settings_page.register — bere specifikaci formuláře: obyčejný slovník popisující strom widgetů. Tyto specifikace stavte pomocníky mte.ui.*, abyste nemuseli psát JSON ručně.

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

Nic v mte.ui nemluví s Qt ani s PySide — každý pomocník vrací slovník podle schématu přenosu, jaké očekává parser formulářů v C++ na straně hostitele. Klidně je skládejte, vkládejte seznamy nebo je generujte programově:

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

Specifikace se ověřuje na straně hostitele; neznámé typy ovládacích prvků nebo chybějící povinná pole vytvoří chybu InvalidParams, kterou uvidíte v protokolu.

Popisky ve specifikaci formuláře se nepřekládají

Každý popisek, který do specifikace vložíte — názvy panelů, popisky zaškrtávacích polí, nadpisy skupin — se zobrazí přesně tak, jak jste jej napsali, ať je jazyk rozhraní jakýkoli. Jsou to data, která váš modul posílá editoru, nikoli řetězce, jež by editor mohl dohledat v překladovém katalogu. Má-li váš modul mluvit více jazyky, zvolte si řetězce sami dřív, než zavoláte register; aktuální jazyk rozhraní je ctx.app_settings.get_string(mte.keys.UI_LANGUAGE) (prázdné znamená »řídit se systémem«). Totéž platí pro name a description, které váš plugin.json zobrazuje v Předvolby ▸ Zásuvné moduly.


Rozvržení

Stavitelé rozvržení berou seznam potomků ve slovnících a uspořádají je svisle nebo vodorovně.

Column(children)

Skládá potomky shora dolů s koncovým roztažením — ovládací prvky si drží svou přirozenou výšku, místo aby se nafoukly a vyplnily vysoký dok.

Row(children)

Tentýž nápad, zleva doprava, s koncovým vodorovným roztažením.

Group(children, *, title="")

Pojmenovaný rámeček (vykreslený jako QGroupBox) obsahující svislý sloupec. Použijte jej k vizuálnímu seskupení souvisejících ovládacích prvků:

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

Rozvržení se volně vnořují — Row uvnitř Column uvnitř Group je v pořádku.


Koncové ovládací prvky

Každý koncový prvek přijímá týchž čtyři sdílené vazby jako pojmenované argumenty:

Argument Význam
id= Stabilní id používané ctx.ui.get / ctx.ui.set a (implicitně) binds.
binds= "settings:<key>" — automatické uchování přes ctx.settings.
on_click= Id příkazu k vyvolání — pouze tlačítka.
on_change= Id obsluhy (ctx.docks.on_change(...)) — každý další ovládací prvek.

binds a on_change podporují pouze koncové prvky, které vystavují »hodnotu«.

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

Statický text.

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

Tlačítko. Spuštění on_click vyvolá zaregistrovaný příkaz; chcete-li tlačítko držet v souladu s něčím jiným, můžete mu pomocí ctx.ui.set nastavit text.

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

Logický ovládací prvek. default je počáteční stav; binds jej přebije uloženou hodnotou, pokud nějaká existuje.

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

Jednořádkový textový vstup.

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

Číselník pro celá čísla. min a max omezují rozsah (obojí volitelné; podkladový QSpinBox používá při nenastavení svůj výchozí rozsah). step je přírůstek na šipkách.

Rozsah int

NumberSpin stojí na QSpinBox, který ukládá int (32bitový). Hodnoty mimo -2_147_483_648 … 2_147_483_647 se zaseknou na limitu platformy.

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

Rozbalovací seznam. items je seznam — každá položka může být buď prostý řetězec, nebo objekt jako {"value": "cpp", "label": "C++"} (dnes se používá pouze value; label je vyhrazeno pro budoucí upřesnění).

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

Seznamový widget s výběrem jedné položky. on_change se spustí s textem nově vybrané položky. Žádné binds — potřebujete-li výběr uchovat, udělejte to sami.


Přístup za běhu

Jakmile je panel zaregistrován, řiďte jej z libovolného příkazu:

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)

Úplnou referenci najdete u ctx.ui.


Uchovávání hodnot

binds="settings:<key>" je nejkratší způsob, jak hodnotu ovládacího prvku uchovat:

  • Při stavbě panelu si widget přečte svou počáteční hodnotu z ctx.settings.get(key, <default>).
  • Při každé úpravě uživatelem widget zapíše zpět přes ctx.settings.set(klíč, nová_hodnota).

Protože panely i stránky Předvoleb sdílejí ctx.settings, dva ovládací prvky se stejným řetězcem binds se navzájem v reálném čase zrcadlí. Právě tak drží dok a stránka Předvoleb v HelloPythonu zaškrtávací pole »Loud« v souladu.

Potřebujete-li uchovat něco, co slovník nepokrývá (například výběr v List), čtěte a zapisujte přímo přes ctx.settings v zavolání on_change.