diff --git a/tools/bluezapi2qt/CppGenerator.cpp b/tools/bluezapi2qt/CppGenerator.cpp index b425574..96dd89c 100644 --- a/tools/bluezapi2qt/CppGenerator.cpp +++ b/tools/bluezapi2qt/CppGenerator.cpp @@ -1,260 +1,259 @@ /* * BluezQt - Asynchronous BlueZ wrapper library * * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include #include #include #include "CppGenerator.h" #include "BluezApiParser.h" #include "TypeAnnotation.h" CppGenerator::CppGenerator(const Config &config) : m_config(config) { } bool CppGenerator::generate(const BluezApiParser &parser) { writeAdaptorHeader(parser); writeAdaptorSource(parser); return true; } void CppGenerator::writeAdaptorHeader(const BluezApiParser &parser) { // Iterate interfaces for (const auto &interface : parser.interfaces()) { auto className = interfaceToClassName(interface.name()); // Create file QFile file(className.toLower() + QStringLiteral("adaptor.h")); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qWarning() << "Error opening file for writing:" << file.fileName(); return; } // Write content QTextStream stream(&file); writeCopyrightHeader(stream); stream << "#pragma once\n\n"; stream << "#include \n\n"; stream << "class QDBusObjectPath;\n\n"; stream << "namespace BluezQt\n{\n\n"; stream << "class " << className << ";\n\n"; stream << "class " << className << "Adaptor : public QDBusAbstractAdaptor\n{\n"; stream << " Q_OBJECT \n"; stream << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface.name() << "\")\n"; // Write properties for (const auto &property : interface.properties().properties()) { // Respect config if ((property.tags().isOptional && !m_config.useOptional) || (property.tags().isExperimental && !m_config.useExperimental)) { continue; } stream << " Q_PROPERTY(" << bluezToQt(property.type()) << " " << property.name() << " READ " << lowerFirstChars(property.name()); if (!property.tags().isReadOnly) { stream << " WRITE set" << property.name(); } stream << ")\n"; } stream << "\npublic:\n"; stream << " explicit " << className << "Adaptor(" << className << "* parent);\n\n"; // Write property accessors for (const auto &property : interface.properties().properties()) { // Respect config if ((property.tags().isOptional && !m_config.useOptional) || (property.tags().isExperimental && !m_config.useExperimental)) { continue; } stream << " " << bluezToQt(property.type()) << " " << lowerFirstChars(property.name()) << "() const;\n"; if (!property.tags().isReadOnly) { stream << " void set" << property.name() << "(const " << bluezToQt(property.type()) << " &" << lowerFirstChars(property.name()) << ");\n"; } stream << "\n"; } stream << "public Q_SLOTS:\n"; // write Methods for (const auto &method : interface.methods().methods()) { // Respect config if ((method.tags().isOptional && !m_config.useOptional) || (method.tags().isExperimental && !m_config.useExperimental)) { continue; } stream << " " << bluezToQt(method.outParameter().type()) << " " << method.name() << "("; for (auto it = method.inParameters().begin(); it != method.inParameters().end(); ++it) { stream << "const " << bluezToQt(it->type()) << " &" << it->name(); if (it != std::prev(method.inParameters().end())) { stream << ", "; } } stream << ");\n"; } // write private members stream << "\nprivate:\n"; stream << " " << className << " *m_" << lowerFirstChars(className) << ";\n"; stream << "};\n\n} // namespace BluezQt\n"; file.close(); } } void CppGenerator::writeAdaptorSource(const BluezApiParser &parser) { // Iterate interfaces for (const auto &interface : parser.interfaces()) { auto className = interfaceToClassName(interface.name()); // Create file QFile file(className.toLower() + QStringLiteral("adaptor.cpp")); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qWarning() << "Error opening file for writing:" << file.fileName(); return; } // Write content QTextStream stream(&file); writeCopyrightHeader(stream); stream << "#include \"" << className << "Adaptor.h\"\n\n"; stream << "#include \"" << className << ".h\"\n\n"; stream << "namespace BluezQt\n{\n\n"; stream << className << "Adaptor::" << className << "Adaptor(" << className << " *parent)\n"; stream << " : QDBusAbstractAdaptor(parent)\n"; stream << " , m_" << lowerFirstChars(className) << "(parent)\n"; stream << "{\n}\n\n"; // Write property accessors for (const auto &property : interface.properties().properties()) { // Respect config if ((property.tags().isOptional && !m_config.useOptional) || (property.tags().isExperimental && !m_config.useExperimental)) { continue; } stream << bluezToQt(property.type()) << " " << className << "Adaptor::" << lowerFirstChars(property.name()) << "() const\n"; stream << "{\n"; stream << " return m_" << lowerFirstChars(className) << "->" << lowerFirstChars(property.name()) << "();\n"; stream << "}\n\n"; if (!property.tags().isReadOnly) { stream << "void " << className << "Adaptor::set" << property.name() << "(const " << bluezToQt(property.type()) << " &" << lowerFirstChars(property.name()) << ");\n"; stream << "{\n"; stream << " m_" << lowerFirstChars(className) << "->set" << property.name() << "(" << lowerFirstChars(property.name()) << ");\n"; stream << "}\n\n"; } } // write Methods for (const auto &method : interface.methods().methods()) { // Respect config if ((method.tags().isOptional && !m_config.useOptional) || (method.tags().isExperimental && !m_config.useExperimental)) { continue; } stream << bluezToQt(method.outParameter().type()) << " " << className << "Adaptor::" << method.name() << "("; for (auto it = method.inParameters().begin(); it != method.inParameters().end(); ++it) { stream << "const " << bluezToQt(it->type()) << " &" << it->name(); if (it != std::prev(method.inParameters().end())) { stream << ", "; } } stream << ")\n{\n"; stream << " return m_" << lowerFirstChars(className) << "->" << lowerFirstChars(method.name()) << "("; for (auto it = method.inParameters().begin(); it != method.inParameters().end(); ++it) { stream << it->name(); if (it != std::prev(method.inParameters().end())) { stream << ", "; } } stream << ");\n}\n\n"; } stream << "} // namespace BluezQt\n"; file.close(); } } QString CppGenerator::interfaceToClassName(const QString &interface) { const int index = interface.lastIndexOf(QRegularExpression(QStringLiteral("\\.[A-Z]\\w+"))) + 1; auto className = interface.mid(index); while (className.back() > L'0' && className.back() <= L'9') { className.remove(className.size()-1, 1); } return className; } QString CppGenerator::lowerFirstChars(const QString &string) { QString str(string); //str.replace(0, 1, string.at(0).toLower()); const QRegularExpression rx(QStringLiteral("^([A-Z]+)")); QRegularExpressionMatch match = rx.match(string); if (match.hasMatch()) { QString matchedStr = match.captured(); for (int i = 0; i < matchedStr.size() - 1; ++i) { str.replace(i, 1, str.at(i).toLower()); } } str.replace(0, 1, string.at(0).toLower()); str.replace(string.size()-1, 1, string.at(string.size()-1).toLower()); return str; } void CppGenerator::writeCopyrightHeader(QTextStream &stream) { stream << "/*\n"; stream << " * BluezQt - Asynchronous Bluez wrapper library\n"; stream << " *\n"; stream << " * Copyright (C) " << m_config.year << " " << m_config.author << "\n"; stream << " *\n"; stream << " * This library is free software; you can redistribute it and/or\n"; stream << " * modify it under the terms of the GNU Lesser General Public\n"; stream << " * License as published by the Free Software Foundation; either\n"; stream << " * version 2.1 of the License, or (at your option) version 3, or any\n"; stream << " * later version accepted by the membership of KDE e.V. (or its\n"; stream << " * successor approved by the membership of KDE e.V.), which shall\n"; stream << " * act as a proxy defined in Section 6 of version 3 of the license.\n"; stream << " *\n"; stream << " * This library is distributed in the hope that it will be useful,\n"; stream << " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"; stream << " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"; stream << " * Lesser General Public License for more details.\n"; stream << " *\n"; stream << " * You should have received a copy of the GNU Lesser General Public\n"; stream << " * License along with this library. If not, see .\n"; stream << " */\n\n"; - stream.flush(); } diff --git a/tools/bluezapi2qt/XmlGenerator.cpp b/tools/bluezapi2qt/XmlGenerator.cpp index 995efee..014fd5b 100644 --- a/tools/bluezapi2qt/XmlGenerator.cpp +++ b/tools/bluezapi2qt/XmlGenerator.cpp @@ -1,163 +1,155 @@ /* * BluezQt - Asynchronous BlueZ wrapper library * * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "XmlGenerator.h" #include #include #include "BluezApiParser.h" #include "TypeAnnotation.h" XmlGenerator::XmlGenerator(const Config &config) : m_config(config) { } bool XmlGenerator::generate(const BluezApiParser &parser) { // Iterate interfaces for (const auto &interface : parser.interfaces()) { // Only consider interfaces with methods if (interface.methods().methods().empty()) { continue; } // Create file QFile file(interface.name() + QStringLiteral(".xml")); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qWarning() << "Error opening file for writing:" << file.fileName(); return false; } // Write content QTextStream stream(&file); writeHeader(stream); writeInterface(stream, interface.name()); // Iterate methods for (const auto &method : interface.methods().methods()) { // Respect config if ((method.tags().isDeprecated && !m_config.useDeprecated) || (method.tags().isOptional && !m_config.useOptional) || (method.tags().isExperimental && !m_config.useExperimental)) { continue; } writeMethod(stream, method); } closeInterface(stream); writeFooter(stream); file.close(); } return true; } void XmlGenerator::writeHeader(QTextStream &stream) { stream << "\n"; stream << "\n"; stream << "\n"; - stream.flush(); } void XmlGenerator::writeFooter(QTextStream &stream) { stream << "\n"; - stream.flush(); } void XmlGenerator::writeInterface(QTextStream &stream, const QString &name) { stream << " \n"; - stream.flush(); } void XmlGenerator::closeInterface(QTextStream &stream) { stream << " \n"; - stream.flush(); } bool XmlGenerator::writeMethod(QTextStream &stream, const Method &method) { stream << " \n"; - stream.flush(); return true; } stream << ">\n"; for (const auto ¶m : method.inParameters()) { if (!writeArg(stream, param, QStringLiteral("in"))) { return false; } } for (const auto ¶m : method.outParameters()) { if (!writeArg(stream, param, QStringLiteral("out"))) { return false; } } for (int i = 0; i < method.inParameters().size(); ++i) { writeAnnotation(stream, method.inParameters().at(i), QStringLiteral("In"), i); } for (int i = 0; i < method.outParameters().size(); ++i) { writeAnnotation(stream, method.outParameters().at(i), QStringLiteral("Out"), i); } stream << " \n"; - stream.flush(); return true; } bool XmlGenerator::writeArg(QTextStream &stream, const Parameter ¶m, const QString &dir) { auto dbusType = annotateType(AnnotationType::Bluez, AnnotationType::Dbus, param.type()); if (dbusType.isEmpty()) { return false; } stream << " \n"; - stream.flush(); return true; } void XmlGenerator::writeAnnotation(QTextStream &stream, const Parameter ¶m, const QString &dir, int i) { auto qtType = annotateType(AnnotationType::Bluez, AnnotationType::Qt, param.type()); if (qtType.isEmpty()) { return; } stream << " \n"; - stream.flush(); return; }