El catálogo de tipos

Módulo de ejemplo: hellotypes.

Los tipos de elemento se dividen en dos familias.

Tipos forzosamente de solo lectura en la interfaz

ElementLight (indicador de estado), ElementImg (imagen), ElementVideo (flujo de vídeo), ElementPrg (barra de progreso o spinner) — ninguno de ellos tiene sentido en escritura directa desde un cliente.

Imagen: la convención webroot

Un módulo escribe su archivo en getWebroot() + "/" + getModuleName() + "/...", y da al elemento una URL relativa a esa ubicación:

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);
getWebroot() todavía no está definido en el constructor

El controlador solo llama a setWebroot() sobre un módulo después de que su constructor retorne. Todo código que escriba un archivo que dependa del webroot debe por tanto diferirse a la siguiente iteración del bucle de eventos:

QTimer::singleShot(0, this, [this]() {
    // getWebroot() est maintenant garanti défini.
});

ElementVideo sigue exactamente la misma convención de URL (OST::VideoData::url), para un flujo ya existente por otra parte.

Barra de progreso y spinner: ambos controlados por un valor

ElementPrg tiene dos presentaciones (prgtype: "bar" o "spinner"), pero ambas están determinadas por un valor 0-100 — un spinner no es un indicador de actividad indeterminada, es un anillo cuyo relleno sigue setPrgValue(), exactamente igual que la barra:

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

Tipos normalmente editables

ElementBool, ElementString, ElementInt, ElementFloat, ElementDate, ElementTime, ElementDateTime — todos pueden bloquearse en solo lectura a nivel de su propiedad (permission:0), independientemente de cualquier ajuste por elemento (directedit, autoupdate): el control de permiso es el primero que se verifica, antes de todo lo demás.

Restricciones numéricas e información sobre herramienta

Para int/float, cuatro claves JSON opcionales adicionales:

"gain": { "type": "float", "directedit": true, "min": 0, "max": 100, "step": 1, "format": "%.0f", "hint": "Gain capteur" }
  • min/max: límites aceptados.
  • step: incremento del control del lado del cliente.
  • format: formato de visualización (estilo printf).
  • hint: información sobre herramienta — disponible en todos los tipos de elemento, no solo los numéricos.

Mezclar tipos en una sola propiedad

A diferencia de INDI, donde un vector solo contiene un único tipo de elemento, una propiedad OST puede mezclar libremente tipos distintos:

"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: el cliente edita el elemento individualmente y lo envía solo (SV) — aplicado de inmediato.
  • directedit:false: el elemento solo puede modificarse mediante un envío agrupado de toda la propiedad (SA) — todos los elementos editables de la propiedad deben incluirse en ese envío, de lo contrario nada se aplica. En el cliente típico, esto corresponde a dos presentaciones distintas: un control de edición inmediata para cada elemento directedit:true, y un formulario con un botón “Guardar” que agrupa todos los elementos directedit:false.

Esta distinción es independiente del tipo: en el ejemplo anterior, bool1/string1/date1 se editan de inmediato, int1/float1 solo mediante el formulario agrupado.