diff --git a/src/cpp.cpp b/src/cpp.cpp --- a/src/cpp.cpp +++ b/src/cpp.cpp @@ -514,6 +514,14 @@ } } } + for (auto f: o.functions) { + h << " Q_INVOKABLE " << f.type.name << " " << f.name << "("; + for (auto a = f.args.begin(); a < f.args.end(); a++) { + h << QString("%1 %2%3").arg(a->type.cppSetType, a->name, a + 1 < f.args.end() ? ", " : ""); + } + h << QString(")%1;") + .arg(f.mut ? "" : " const"); + } if (baseType(o) == "QAbstractItemModel") { writeHeaderItemModel(h, o); } @@ -678,6 +686,22 @@ } } } + + for (const Function& f: o.functions) { + const QString name = QString("%1_%2").arg(lcname, f.name); + cpp << QString(" %1 %2(%4%3::Private*") + .arg(f.type.cSetType, name, o.name, f.mut ? "" : "const "); + if (f.args.size() > 0) { + cpp << ", "; + for (auto a = f.args.begin(); a < f.args.end(); a++) { + cpp << QString("%2%3").arg(a->type.cSetType, a + 1 < f.args.end() ? ", " : ""); + } + } + if (f.type.name == "QString") { + cpp << ", QString*, qstring_set"; + } + cpp << ");" << endl; + } } void initializeMembersEmpty(QTextStream& cpp, const Object& o, const Configuration& conf) @@ -811,6 +835,35 @@ cpp << "}" << endl; } } + + for (const Function& f: o.functions) { + const QString base = QString("%1_%2") + .arg(lcname, snakeCase(f.name)); + cpp << QString("%1 %2::%3(") + .arg(f.type.name, o.name, f.name); + for (auto a = f.args.begin(); a < f.args.end(); a++) { + cpp << QString("%1 %2%3").arg(a->type.cppSetType, a->name, a + 1 < f.args.end() ? ", " : ""); + } + cpp << QString(") %4\n{\n") + .arg(f.mut ? "" : "const"); + QString argList; + if (f.args.size() > 0) { + argList.append(", "); + for (auto a = f.args.begin(); a < f.args.end(); a++) { + argList.append(QString("%2%3").arg(a->name, a + 1 < f.args.end() ? ", " : "")); + } + } + if (f.type.name == "QString") { + cpp << QString(" %1 s;").arg(f.type.name) << endl; + cpp << QString(" %1(m_d%2, &s, set_qstring);") + .arg(base, argList) << endl; + cpp << " return s;" << endl; + } else { + cpp << QString(" return %1(m_d%2);") + .arg(base, argList) << endl; + } + cpp << "}" << endl; + } } void writeHeader(const Configuration& conf) { diff --git a/src/parseJson.cpp b/src/parseJson.cpp --- a/src/parseJson.cpp +++ b/src/parseJson.cpp @@ -133,6 +133,33 @@ return p; } +Argument +parseArgument(const QJsonObject& json) { + Argument arg; + arg.name = json.value("name").toString(); + arg.type = parseBindingType(json.value("type").toString()); + return arg; +} + +QList +parseArguments(const QJsonArray& json) { + QList args; + for(const auto& a: json) { + args.push_back(parseArgument(a.toObject())); + } + return args; +} + +Function +parseFunction(const QString& name, const QJsonObject& json) { + Function f; + f.name = name; + f.mut = json.value("mut").toBool(); + f.type = parseBindingType(json.value("return").toString()); + f.args = parseArguments(json.value("arguments").toArray()); + return f; +} + Qt::ItemDataRole parseItemDataRole(const QString& s) { const QString name = s.left(1).toUpper() + s.mid(1) + "Role"; int v = QMetaEnum::fromType() @@ -182,6 +209,10 @@ for (const QString& key: properties.keys()) { o.properties.append(parseProperty(key, properties[key].toObject())); } + const QJsonObject& functions = json.value("functions").toObject(); + for (const QString& key: functions.keys()) { + o.functions.append(parseFunction(key, functions[key].toObject())); + } QTextStream err(stderr); const QJsonObject& itemProperties = json.value("itemProperties").toObject(); if (o.type != ObjectType::Object && itemProperties.size() == 0) { diff --git a/src/rust.cpp b/src/rust.cpp --- a/src/rust.cpp +++ b/src/rust.cpp @@ -282,6 +282,21 @@ } } } + for (const Function& f: o.functions) { + const QString lc(snakeCase(f.name)); + QString argList; + if (f.args.size() > 0) { + argList.append(", "); + for (auto a = f.args.begin(); a < f.args.end(); a++) { + argList.append( + QString("%1: %2%3") + .arg(a->name, a->type.rustType, a + 1 < f.args.end() ? ", " : "") + ); + } + } + r << QString(" fn %1(&%2self%4) -> %3;\n") + .arg(lc, f.mut ? "mut " : "", f.type.rustType, argList); + } if (o.type == ObjectType::List) { r << R"( fn row_count(&self) -> usize; fn insert_rows(&mut self, row: usize, count: usize) -> bool { false } @@ -409,6 +424,36 @@ } } } + for (const Function& f: o.functions) { + QString argList; + QString noTypeArgs; + if (f.args.size() > 0) { + argList.append(", "); + for (auto a = f.args.begin(); a < f.args.end(); a++) { + const QString type = a->type.name == "QString" ? "QStringIn" : a->type.rustType; + const QString passAlong = a->type.name == "QString" ? QString("%1.convert()").arg(a->name) : a->name; + argList.append(QString("%1: %2%3").arg(a->name, type, a + 1 < f.args.end() ? ", " : "")); + noTypeArgs.append(QString("%1%3").arg(passAlong, a + 1 < f.args.end() ? ", " : "")); + } + } + if (f.type.isComplex()) { + r << QString(R"( +#[no_mangle] +pub unsafe extern "C" fn %1_%2(ptr: *%3 %4%7, d: *mut c_void, set: fn(*mut c_void, %5)) { + let data = (&%6*ptr).%2(%8); + set(d, (&data).into()); +} +)").arg(lcname, f.name, f.mut ? "mut" : "const", o.name, f.type.name, f.mut ? "mut " : "", argList, noTypeArgs); + + } else { + r << QString(R"( +#[no_mangle] +pub unsafe extern "C" fn %1_%2(ptr: *%3 %4%7) -> %5 { + (&%6*ptr).%2(%8) +} +)").arg(lcname, f.name, f.mut ? "mut" : "const", o.name, f.type.rustType, f.mut ? "mut " : "", argList, noTypeArgs); + } + } if (o.type == ObjectType::List) { r << QString(R"( #[no_mangle] diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -72,6 +72,18 @@ bool rustByValue; }; +struct Argument { + QString name; + BindingTypeProperties type; +}; + +struct Function { + QString name; + BindingTypeProperties type; + QList args; + bool mut; +}; + struct ItemProperty { QString name; BindingTypeProperties type; @@ -86,6 +98,7 @@ ObjectType type; QList properties; QList itemProperties; + QList functions; int columnCount; bool containsObject() { for (auto p: properties) {