50#include <QJsonDocument>
65static QMetaType::Type metaTypeFromString(
const QString& str)
67 if (str == QLatin1String(
"string"))
return QMetaType::QString;
68 if (str == QLatin1String(
"double"))
return QMetaType::Double;
69 if (str == QLatin1String(
"float"))
return QMetaType::Float;
70 if (str == QLatin1String(
"int"))
return QMetaType::Int;
71 if (str == QLatin1String(
"bool"))
return QMetaType::Bool;
72 if (str == QLatin1String(
"path"))
return QMetaType::QString;
73 return QMetaType::QString;
78static QString metaTypeToString(QMetaType::Type type)
81 case QMetaType::QString:
return QStringLiteral(
"string");
82 case QMetaType::Double:
return QStringLiteral(
"double");
83 case QMetaType::Float:
return QStringLiteral(
"float");
84 case QMetaType::Int:
return QStringLiteral(
"int");
85 case QMetaType::Bool:
return QStringLiteral(
"bool");
86 default:
return QStringLiteral(
"string");
95 port.
name = obj.value(QLatin1String(
"name")).toString();
97 port.
required = obj.value(QLatin1String(
"required")).toBool(
true);
98 port.
description = obj.value(QLatin1String(
"description")).toString();
107 obj[QLatin1String(
"name")] = port.
name;
109 obj[QLatin1String(
"description")] = port.
description;
111 obj[QLatin1String(
"required")] =
false;
120 attr.
name = obj.value(QLatin1String(
"name")).toString();
121 attr.
type = metaTypeFromString(obj.value(QLatin1String(
"type")).toString());
122 attr.
required = obj.value(QLatin1String(
"required")).toBool(
false);
123 attr.
description = obj.value(QLatin1String(
"description")).toString();
124 if (obj.contains(QLatin1String(
"default")))
125 attr.
defaultValue = obj.value(QLatin1String(
"default")).toVariant();
134 obj[QLatin1String(
"name")] = attr.
name;
135 obj[QLatin1String(
"type")] = metaTypeToString(attr.
type);
137 obj[QLatin1String(
"required")] =
true;
139 obj[QLatin1String(
"description")] = attr.
description;
141 obj[QLatin1String(
"default")] = QJsonValue::fromVariant(attr.
defaultValue);
150 schema.
opType = obj.value(QLatin1String(
"type")).toString();
151 schema.
version = obj.value(QLatin1String(
"version")).toString();
152 schema.
binding = obj.value(QLatin1String(
"binding")).toString(QStringLiteral(
"internal"));
153 schema.
category = obj.value(QLatin1String(
"category")).toString();
154 schema.
description = obj.value(QLatin1String(
"description")).toString();
155 schema.
library = obj.value(QLatin1String(
"library")).toString();
156 schema.
executable = obj.value(QLatin1String(
"executable")).toString();
157 schema.
cliTemplate = obj.value(QLatin1String(
"cli_template")).toString();
159 const QJsonArray inputs = obj.value(QLatin1String(
"inputs")).toArray();
160 for (
const QJsonValue& v : inputs)
161 schema.
inputPorts.append(parsePort(v.toObject()));
163 const QJsonArray outputs = obj.value(QLatin1String(
"outputs")).toArray();
164 for (
const QJsonValue& v : outputs)
165 schema.
outputPorts.append(parsePort(v.toObject()));
167 const QJsonArray params = obj.value(QLatin1String(
"parameters")).toArray();
168 for (
const QJsonValue& v : params)
169 schema.
attributes.append(parseAttr(v.toObject()));
176static QJsonObject opToJson(
const MnaOpSchema& schema)
179 obj[QLatin1String(
"type")] = schema.
opType;
180 obj[QLatin1String(
"description")] = schema.
description;
183 obj[QLatin1String(
"version")] = schema.
version;
185 obj[QLatin1String(
"binding")] = schema.
binding;
187 obj[QLatin1String(
"category")] = schema.
category;
189 obj[QLatin1String(
"library")] = schema.
library;
191 obj[QLatin1String(
"executable")] = schema.
executable;
193 obj[QLatin1String(
"cli_template")] = schema.
cliTemplate;
197 inputs.append(portToJson(p));
198 obj[QLatin1String(
"inputs")] = inputs;
202 outputs.append(portToJson(p));
203 obj[QLatin1String(
"outputs")] = outputs;
207 params.append(attrToJson(a));
208 obj[QLatin1String(
"parameters")] = params;
220 if (!file.open(QIODevice::ReadOnly)) {
221 qWarning() <<
"MnaRegistryLoader: Cannot open" << path;
225 QJsonParseError parseError;
226 QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &parseError);
229 if (parseError.error != QJsonParseError::NoError) {
230 qWarning() <<
"MnaRegistryLoader: JSON parse error in" << path
231 <<
":" << parseError.errorString();
235 const QJsonObject root = doc.object();
238 if (!root.contains(QLatin1String(
"mna_registry_version"))) {
239 qWarning() <<
"MnaRegistryLoader: Missing 'mna_registry_version' in" << path;
243 const QJsonArray ops = root.value(QLatin1String(
"ops")).toArray();
246 for (
const QJsonValue& v : ops) {
248 if (!schema.
opType.isEmpty()) {
254 qInfo() <<
"MnaRegistryLoader: Loaded" << count <<
"ops from" << path
255 <<
"(provider:" << root.value(QLatin1String(
"provider")).toString() <<
")";
267 QString masterPath = registryDir + QStringLiteral(
"/mna-registry.json");
268 if (QFile::exists(masterPath)) {
269 int n =
loadFile(masterPath, registry);
270 if (n > 0) total += n;
274 QDir dropInDir(registryDir + QStringLiteral(
"/mna-registry.d"));
275 if (dropInDir.exists()) {
277 filters << QStringLiteral(
"*.json");
278 QStringList files = dropInDir.entryList(filters, QDir::Files, QDir::Name);
279 for (
const QString& fileName : files) {
280 int n =
loadFile(dropInDir.absoluteFilePath(fileName), registry);
281 if (n > 0) total += n;
291 const QString& provider,
295 root[QLatin1String(
"mna_registry_version")] = QStringLiteral(
"1.0");
296 root[QLatin1String(
"provider")] = provider;
300 for (
const QString& opType : opTypes)
301 ops.append(opToJson(registry.
schema(opType)));
302 root[QLatin1String(
"ops")] = ops;
305 if (!file.open(QIODevice::WriteOnly)) {
306 qWarning() <<
"MnaRegistryLoader: Cannot write" << path;
310 file.write(QJsonDocument(root).toJson(QJsonDocument::Indented));
MnaOpSchema class declaration — contract for graph operations.
MnaOpRegistry class declaration — singleton catalog of operation schemas.
MnaRegistryLoader class declaration — loads MNA op schemas from JSON manifests.
MNE Analysis Container Format (mna/mnx).
QString mnaDataKindToString(MnaDataKind kind)
MnaDataKind mnaDataKindFromString(const QString &str)
Operation registry for the MNA graph model.
QStringList registeredOps() const
void registerOp(const MnaOpSchema &schema)
MnaOpSchema schema(const QString &opType) const
bool required
Must be connected?
QString description
Human-readable description.
MnaDataKind dataKind
Expected data kind.
QVariant defaultValue
Default when not set.
QMetaType::Type type
Expected value type.
QString description
Human-readable description.
QString name
Attribute key.
bool required
Must be set?
Operation schema for graph validation.
QList< MnaOpSchemaPort > outputPorts
Expected output ports.
QString binding
Binding type: "internal", "cli", or "script".
QList< MnaOpSchemaPort > inputPorts
Expected input ports.
QList< MnaOpSchemaAttr > attributes
Expected attributes.
QString category
Category: "io", "preprocessing", "source_estimation", etc.
QString opType
Operation type string.
QString version
Version of the operation (e.g. "2.2.0").
QString executable
For CLI ops: executable name (e.g. "recon-all").
QString library
Which library provides the implementation.
QString description
What the operation does.
QString cliTemplate
For CLI ops: command template with {{placeholder}} tokens.
static bool saveFile(const QString &path, const QString &provider, const MnaOpRegistry ®istry)
static int loadDirectory(const QString ®istryDir, MnaOpRegistry ®istry)
static int loadFile(const QString &path, MnaOpRegistry ®istry)