The type catalog
Example module: hellotypes.
Element types fall into two families.
Types that are necessarily read-only on the interface side
ElementLight (status indicator), ElementImg (image), ElementVideo (video stream), ElementPrg (progress bar or spinner) — none of them make sense as a direct write from a client.
Image: the webroot convention
A module writes its file to getWebroot() + "/" + getModuleName() + "/...", and gives the element a URL relative to that location:
QDir dir;
dir.mkdir(getWebroot() + "/" + getModuleName());
atomicSaveJpeg(img, getWebroot() + "/" + getModuleName() + "/photo.jpeg");
OST::ImgData data;
data.mUrlJpeg = getModuleName() + "/photo.jpeg";
getEltImg("display", "photo")->setValue(data, true);The controller only calls setWebroot() on a module after its constructor has returned. Any code that writes a file depending on the webroot must therefore be deferred to the next iteration of the event loop:
QTimer::singleShot(0, this, [this]() {
// getWebroot() est maintenant garanti défini.
});ElementVideo follows exactly the same URL convention (OST::VideoData::url), for a stream that already exists elsewhere.
Progress bar and spinner: both driven by a value
ElementPrg has two presentations (prgtype: "bar" or "spinner"), but both are driven by a 0-100 value — a spinner is not an indeterminate activity indicator, it’s a ring whose fill follows setPrgValue(), exactly like the bar:
getEltPrg("display", "progress")->setPrgValue(42.0, true);
getEltPrg("display", "spinner")->setPrgValue(42.0, true); // oui, le spinner aussi
getEltPrg("display", "spinner")->setDynLabel("En cours...", true);Normally editable types
ElementBool, ElementString, ElementInt, ElementFloat, ElementDate, ElementTime, ElementDateTime — all of them can be locked to read-only at the level of their property (permission:0), independently of any per-element setting (directedit, autoupdate): the permission check is the first one applied, ahead of everything else.
Numeric constraints and tooltip
For int/float, four additional optional JSON keys:
"gain": { "type": "float", "directedit": true, "min": 0, "max": 100, "step": 1, "format": "%.0f", "hint": "Gain capteur" }min/max: accepted bounds.step: increment of the control on the client side.format: display format (printf-style).hint: tooltip — available on all element types, not just numeric ones.
Mixing types within a single property
Unlike INDI, where a vector only ever contains a single element type, an OST property can freely mix different types:
"editabledata": {
"permission": 2,
"e": {
"bool1": { "type": "bool", "directedit": true },
"string1": { "type": "string", "directedit": true },
"int1": { "type": "int" },
"float1": { "type": "float" },
"date1": { "type": "date", "directedit": true }
}
}directedit:true vs directedit:false
directedit:true: the client edits the element individually and sends it on its own (SV) — applied immediately.directedit:false: the element can only be modified via a grouped send of the whole property (SA) — all editable elements of the property must be included in that send, otherwise nothing is applied. On a typical client, this corresponds to two different presentations: an immediate-edit control for eachdirectedit:trueelement, and a form with a “Save” button grouping all thedirectedit:falseelements.
This distinction is independent of type: in the example above, bool1/string1/date1 are edited immediately, int1/float1 only through the grouped form.