diff options
-rw-r--r-- | .travis.yml | 15 | ||||
-rw-r--r-- | CMakeLists.txt | 25 | ||||
-rw-r--r-- | connection.cpp | 3 | ||||
-rw-r--r-- | converters.h | 4 | ||||
-rw-r--r-- | jobs/basejob.cpp | 1 | ||||
-rw-r--r-- | jobs/gtad.yaml | 79 | ||||
-rw-r--r-- | jobs/preamble.mustache | 3 | ||||
-rw-r--r-- | jobs/{{base}}.cpp.mustache | 101 | ||||
-rw-r--r-- | jobs/{{base}}.h.mustache | 61 |
9 files changed, 283 insertions, 9 deletions
diff --git a/.travis.yml b/.travis.yml index 1b67119d..9c7d8a7d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,9 +23,20 @@ before_install: - eval "${ENV_EVAL}" - if [ "$TRAVIS_OS_NAME" = "linux" ]; then . /opt/qt56/bin/qt56-env.sh; fi -script: +install: +- git clone https://github.com/QMatrixClient/matrix-doc.git +- git clone --recursive https://github.com/KitsuneRal/gtad.git +- pushd gtad +- cmake -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} . +- cmake --build . +- popd + +before_script: - mkdir build && cd build -- cmake .. +- cmake -DMATRIX_DOC_PATH="matrix-doc" -DGTAD_PATH="gtad/gtad" -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} .. +- cmake --build . --target update-api + +script: - cmake --build . --target all - cd .. - qmake qmc-example.pro "QMAKE_CC = $CC" "QMAKE_CXX = $CXX" && make all diff --git a/CMakeLists.txt b/CMakeLists.txt index 463bfea7..1aa06198 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,11 @@ if (CMAKE_BUILD_TYPE) endif(CMAKE_BUILD_TYPE) message( STATUS "Using compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}" ) message( STATUS "Using Qt ${Qt5_VERSION} at ${Qt5_Prefix}" ) +if (MATRIX_DOC_PATH AND GTAD_PATH) + message( STATUS "Generating API stubs enabled" ) + message( STATUS " Using GTAD at ${GTAD_PATH}" ) + message( STATUS " Using CS API files at ${MATRIX_DOC_PATH}/api/client-server" ) +endif () message( STATUS "=============================================================================" ) message( STATUS ) @@ -70,6 +75,26 @@ set(libqmatrixclient_SRCS jobs/mediathumbnailjob.cpp ) +set(API_DEF_PATH ${MATRIX_DOC_PATH}/api/client-server/) +file(GLOB_RECURSE API_DEFS RELATIVE ${PROJECT_SOURCE_DIR} + ${API_DEF_PATH}/*.yaml + ${API_DEF_PATH}/definitions/*.yaml + ${MATRIX_DOC_PATH}/event-schemas/schema/* +) +if (MATRIX_DOC_PATH AND GTAD_PATH) + add_custom_target(update-api + ${GTAD_PATH} --config jobs/gtad.yaml --out jobs/generated + ${MATRIX_DOC_PATH}/api/client-server + cas_login_redirect.yaml- cas_login_ticket.yaml- + old_sync.yaml- room_initial_sync.yaml- + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + SOURCES jobs/gtad.yaml + jobs/{{base}}.h.mustache jobs/{{base}}.cpp.mustache + ${API_DEFS} + VERBATIM + ) +endif() + aux_source_directory(jobs/generated libqmatrixclient_job_SRCS) set(example_SRCS examples/qmc-example.cpp) diff --git a/connection.cpp b/connection.cpp index 8765950a..36da838f 100644 --- a/connection.cpp +++ b/connection.cpp @@ -187,8 +187,7 @@ void Connection::Private::connectWithToken(const QString& user, data->setToken(accessToken.toLatin1()); data->setDeviceId(deviceId); qCDebug(MAIN) << "Using server" << data->baseUrl() << "by user" - << userId - << "from device" << deviceId; + << userId << "from device" << deviceId; emit q->connected(); } diff --git a/converters.h b/converters.h index 00d1d339..0d7f734e 100644 --- a/converters.h +++ b/converters.h @@ -46,11 +46,7 @@ namespace QMatrixClient inline QJsonValue toJson(const QByteArray& bytes) { -#if QT_VERSION < QT_VERSION_CHECK(5, 3, 0) - return QJsonValue(QLatin1String(bytes.constData())); -#else return QJsonValue(bytes.constData()); -#endif } template <typename T> diff --git a/jobs/basejob.cpp b/jobs/basejob.cpp index 8d116c26..405cb9e0 100644 --- a/jobs/basejob.cpp +++ b/jobs/basejob.cpp @@ -25,7 +25,6 @@ #include <QtNetwork/QNetworkReply> #include <QtCore/QTimer> #include <QtCore/QRegularExpression> -//#include <QtCore/QStringBuilder> #include <array> diff --git a/jobs/gtad.yaml b/jobs/gtad.yaml new file mode 100644 index 00000000..a19415a6 --- /dev/null +++ b/jobs/gtad.yaml @@ -0,0 +1,79 @@ +preprocess: + "%CLIENT_RELEASE_LABEL%": r0 + "%CLIENT_MAJOR_VERSION%": r0 + # FIXME: the below only fixes C++ compilation but not actual work - the code + # will try to reach out for wrong values in JSON payloads + "signed:": "signedData:" + "unsigned:": "unsignedData:" + "default:": "isDefault:" + +# Structure: +# swaggerType: <targetTypeSpec> +# OR +# swaggerType: +# - swaggerFormat: <targetTypeSpec> +# - /swaggerFormatRegEx/: <targetTypeSpec> +# - //: <targetTypeSpec> # default, if the format doesn't mach anything above +# WHERE +# targetTypeSpec = targetType OR +# { type: targetType, imports: <filename OR [ filenames... ]>, <other attributes...> } +types: + integer: + - int64: qint64 + - int32: qint32 + - //: int + number: + - float: float + - //: double + boolean: bool + string: + - byte: &QByteArray + type: QByteArray + string?: true + imports: <QtCore/QByteArray> + - binary: *QByteArray + - date: { type: QDate, "avoidCopy?": true, imports: <QtCore/QDate> } + - dateTime: + type: QDateTime + avoidCopy?: true + imports: <QtCore/QDateTime> + - //: + type: QString + string?: true + avoidCopy?: true + imports: <QtCore/QString> + file: + type: QByteArray + imports: <QtCore/QByteArray> + returnFile?: true + object: + type: QJsonObject + avoidCopy?: true + imports: <QtCore/QJsonObject> + array: + - /.+/: + type: "QVector<{{1}}>" + avoidCopy?: true + imports: <QtCore/QVector> + - //: { type: QJsonArray, "avoidCopy?": true, imports: <QtCore/QJsonArray> } + schema: + avoidCopy?: true + +#operations: + +env: + _typeRenderer: "{{#scope}}{{scopeCamelCase}}Job::{{/scope}}{{name}}" + maybeCrefType: "{{#avoidCopy?}}const {{/avoidCopy?}}{{dataType.name}}{{#avoidCopy?}}&{{/avoidCopy?}}" + qualifiedMaybeCrefType: "{{#avoidCopy?}}const {{/avoidCopy?}}{{dataType.qualifiedName}}{{#avoidCopy?}}&{{/avoidCopy?}}" +# preamble: preamble.mustache + copyrightName: Kitsune Ral + copyrightEmail: <kitsune-ral@users.sf.net> +# imports: { set: } +# returnFile?: { bool: false } + +templates: +- "{{base}}.h.mustache" +- "{{base}}.cpp.mustache" + +#outFilesList: apifiles.txt + diff --git a/jobs/preamble.mustache b/jobs/preamble.mustache new file mode 100644 index 00000000..3ba87d61 --- /dev/null +++ b/jobs/preamble.mustache @@ -0,0 +1,3 @@ +/****************************************************************************** + * THIS FILE IS GENERATED - ANY EDITS WILL BE OVERWRITTEN + */ diff --git a/jobs/{{base}}.cpp.mustache b/jobs/{{base}}.cpp.mustache new file mode 100644 index 00000000..b303c053 --- /dev/null +++ b/jobs/{{base}}.cpp.mustache @@ -0,0 +1,101 @@ +{{#@filePartial}}preamble{{/@filePartial}} + +#include "{{filenameBase}}.h" + +#include "converters.h" +{{#operations}} +#include <QtCore/QStringBuilder> +{{/operations}} +using namespace QMatrixClient; +{{#models.model}}{{^trivial?}} +{{qualifiedName}}::operator QJsonValue() const +{ + QJsonObject o; + {{#vars}}o.insert("{{baseName}}", toJson({{nameCamelCase}})); + {{/vars}} + return o; +} + +{{qualifiedName}} FromJson<{{qualifiedName}}>::operator()(QJsonValue jv) +{ + QJsonObject o = jv.toObject(); + {{qualifiedName}} result; + {{#vars}}result.{{nameCamelCase}} = + fromJson<{{dataType.name}}>(o.value("{{baseName}}")); + {{/vars}} + return result; +} +{{/trivial?}}{{/models.model}}{{#operations}} +static const auto basePath = QStringLiteral("{{basePathWithoutHost}}"); +{{# operation}}{{#models.model}}{{^trivial?}} +{{qualifiedName}}::operator QJsonObject() const +{ + QJsonObject o; + {{#vars}}o.insert("{{baseName}}", toJson({{nameCamelCase}})); + {{/vars}} + return o; +} +namespace QMatrixClient +{ + template <> struct FromJson<{{qualifiedName}}> + { + {{qualifiedName}} operator()(QJsonValue jv) + { + QJsonObject o = jv.toObject(); + {{qualifiedName}} result; + {{#vars}}result.{{nameCamelCase}} = + fromJson<{{dataType.qualifiedName}}>(o.value("{{baseName}}")); + {{/vars}} + return result; + } + }; +} // namespace QMatrixClient +{{/ trivial?}}{{/models.model}}{{#responses}}{{#normalResponse?}}{{#properties?}} +class {{camelCaseOperationId}}Job::Private +{ + public: + {{#properties}}{{dataType.name}} {{paramName}};{{#@join}}{{!EOL except the last line}} + {{/@join}}{{/properties}} +}; +{{/ properties?}}{{/normalResponse?}}{{/responses}} +{{camelCaseOperationId}}Job::{{camelCaseOperationId}}Job({{#allParams}}{{>maybeCrefType}} {{paramName}}{{#@join}}, {{/@join}}{{/allParams}}) + : BaseJob(HttpVerb::{{#@cap}}{{#@tolower}}{{httpMethod}}{{/@tolower}}{{/@cap}}, "{{camelCaseOperationId}}Job", + basePath{{#pathParts}} % {{_}}{{/pathParts}}, + Query {{^queryParams}}{ }{{/queryParams}}{{#queryParams?}}{ + {{#queryParams}}{ "{{baseName}}", toJson({{paramName}}).toString() }{{#@join}}, + {{/@join}}{{/queryParams}} + }{{/queryParams?}}{{#skipAuth}}, Data { }, false{{/skipAuth}} + ){{#responses}}{{#normalResponse?}}{{#properties?}}, d(new Private){{/properties?}}{{/normalResponse?}}{{/responses}} +{{#bodyParams?}}{ +{{#inlineBody}} setRequestData(Data({{paramName}}));{{/inlineBody}}{{! +}}{{^inlineBody}} QJsonObject _data;{{#bodyParams}} +{{^required?}}{{#string?}} if (!{{paramName}}.isEmpty()) + {{/string?}}{{/required?}} _data.insert("{{baseName}}", toJson({{paramName}}));{{/bodyParams}} + setRequestData(_data);{{/inlineBody}} +}{{/bodyParams?}}{{^bodyParams?}}{ }{{/bodyParams?}} +{{# responses}}{{#normalResponse?}}{{#properties?}} +{{camelCaseOperationId}}Job::~{{camelCaseOperationId}}Job() +{ + delete d; +} +{{# properties}} +{{>qualifiedMaybeCrefType}} {{camelCaseOperationId}}Job::{{paramName}}() const +{ + return d->{{paramName}}; +} +{{/ properties}}{{#returnFile?}} +BaseJob::Status {{camelCaseOperationId}}Job::parseReply(QByteArray data) +{ + {{properties.nameCamelCase}} = data; + return Success; +}{{/ returnFile?}}{{^returnFile?}} +BaseJob::Status {{camelCaseOperationId}}Job::parseJson(const QJsonDocument& data) +{ + auto json = data.object(); + {{# properties}}{{#required?}}if (!json.contains("{{baseName}}")) + return { JsonParseError, + "The key '{{baseName}}' not found in the response" }; + {{/required?}}d->{{paramName}} = fromJson<{{dataType.name}}>(json.value("{{baseName}}")); + {{/ properties}}return Success; +}{{/ returnFile?}} +{{/properties?}}{{/normalResponse?}}{{/responses}}{{/operation}}{{/operations}} diff --git a/jobs/{{base}}.h.mustache b/jobs/{{base}}.h.mustache new file mode 100644 index 00000000..76ae4f51 --- /dev/null +++ b/jobs/{{base}}.h.mustache @@ -0,0 +1,61 @@ +{{#@filePartial}}preamble{{/@filePartial}} + +#pragma once + +{{#operations}}#include "../basejob.h" +{{/operations}} +{{#imports}}#include {{_}} +{{/imports}} +{{#allModels}}#include "converters.h" +{{/allModels}} +namespace QMatrixClient +{ +{{#models}} // Data structures +{{# model}}{{#trivial?}} + using {{name}} = {{parent.name}}; +{{/ trivial?}}{{^trivial?}} + struct {{name}}{{#parents?}} : {{#parents}}{{name}}{{#@join}}, {{/@join}}{{/parents}}{{/parents?}} + { + {{#vars}}{{dataType.name}} {{nameCamelCase}}; + {{/vars}} + operator QJsonObject() const; + }; + + template <> struct FromJson<{{name}}> + { + {{name}} operator()(QJsonValue jv); + }; +{{/ trivial?}}{{/model}} +{{/models}}{{#operations}} // Operations +{{# operation}} + class {{camelCaseOperationId}}Job : public BaseJob + { + public:{{# models}} + // Inner data structures +{{# model}}{{#trivial?}} + using {{name}} = {{parent.name}}; +{{/ trivial?}}{{^trivial?}} + struct {{name}}{{#parents?}} : {{#parents}}{{name}}{{#@join}}, {{/@join}}{{/parents}}{{/parents?}} + { + {{#vars}}{{dataType.name}} {{nameCamelCase}}; + {{/vars}} + operator QJsonObject() const; + }; +{{/ trivial?}}{{/model}} + // End of inner data structures +{{/models}} + explicit {{camelCaseOperationId}}Job({{#allParams}}{{>maybeCrefType}} {{paramName}}{{^required?}} = {{defaultValue}}{{^defaultValue}}{}{{/defaultValue}}{{/required?}}{{#@join}}, {{/@join}}{{/allParams}});{{!skip EOL +}}{{# responses}}{{#normalResponse?}}{{#properties?}} + ~{{camelCaseOperationId}}Job() override; + + {{#properties}}{{>maybeCrefType}} {{paramName}}() const; + {{/properties}} + protected: + {{^returnFile}}Status parseJson(const QJsonDocument& data) override;{{/returnFile}} + {{#returnFile?}}Status parseReply(QByteArray data) override;{{/returnFile?}} + private: + class Private; + Private* d;{{/properties?}}{{/normalResponse?}}{{/responses}} + }; +{{/operation}}{{/operations}}{{!skip EOL +}}} // namespace QMatrixClient |