22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |  |
30 |
31 |
32 |
33 | $projectname
34 | $projectnumber
35 |
36 | $projectbrief
37 | |
38 |
39 |
40 |
41 |
42 | $projectbrief
43 | |
44 |
45 |
46 |
47 |
48 | $searchbox |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/tests/auto/restclient/testlib/testlib.h:
--------------------------------------------------------------------------------
1 | #ifndef TESTLIB_H
2 | #define TESTLIB_H
3 |
4 | #include
5 | #include
6 | #include "jphpost.h"
7 | #include "httpserver.h"
8 |
9 | #include
10 |
11 | class BodyType : public std::variant
12 | {
13 | public:
14 | BodyType() = default;
15 | BodyType(const BodyType &other) = default;
16 | BodyType(BodyType &&other) noexcept = default;
17 | BodyType &operator=(const BodyType &other) = default;
18 | BodyType &operator=(BodyType &&other) noexcept = default;
19 |
20 | BodyType(QCborValue data);
21 | BodyType(QCborMap data);
22 | BodyType(QCborArray data);
23 | BodyType(QJsonValue data);
24 | BodyType(QJsonObject data);
25 | BodyType(QJsonArray data);
26 |
27 | explicit BodyType(const QtRestClient::RestReply::DataType &data);
28 |
29 | static BodyType parse(QNetworkReply *reply);
30 |
31 | bool isValid() const;
32 | QByteArray accept() const;
33 | void setAccept(QNetworkRequest &request) const;
34 | QVariant toVariant() const;
35 |
36 | template
37 | inline auto visit(TFn &&fn) {
38 | return std::visit(std::forward(fn), static_cast>(*this));
39 | }
40 | template
41 | inline auto visit(TFn &&fn) const {
42 | return std::visit(std::forward(fn), static_cast>(*this));
43 | }
44 |
45 | bool operator==(const BodyType &other) const;
46 | bool operator!=(const BodyType &other) const;
47 | bool operator<(const BodyType &other) const = delete;
48 | };
49 |
50 | QDebug operator<<(QDebug debug, const BodyType &data);
51 |
52 | class Testlib
53 | {
54 | public:
55 | inline static BodyType CBody(QCborValue value = QCborValue::Undefined) {
56 | return BodyType{std::move(value)};
57 | }
58 | inline static BodyType CBody(const QJsonValue &value) {
59 | return BodyType{QCborValue::fromJsonValue(value)};
60 | }
61 | inline static BodyType JBody(QJsonValue value = QJsonValue::Undefined) {
62 | return BodyType{std::move(value)};
63 | }
64 | inline static BodyType JBody(const QCborValue &value) {
65 | return BodyType{value.toJsonValue()};
66 | }
67 |
68 | static QtRestClient::RestClient *createClient(QObject *parent = nullptr);
69 | static void setAccept(QNetworkRequest &request, QtRestClient::RestClient *client);
70 | };
71 |
72 | Q_DECLARE_METATYPE(QUrlQuery)
73 | Q_DECLARE_METATYPE(QNetworkRequest::Attribute)
74 | Q_DECLARE_METATYPE(BodyType)
75 |
76 | #endif // TESTLIB_H
77 |
--------------------------------------------------------------------------------
/tests/auto/restclient/RestClientTest/tst_restclient.cpp:
--------------------------------------------------------------------------------
1 | #include "testlib.h"
2 |
3 | class RestClientTest : public QObject
4 | {
5 | Q_OBJECT
6 |
7 | private Q_SLOTS:
8 | void testBaseUrl_data();
9 | void testBaseUrl();
10 | };
11 |
12 | void RestClientTest::testBaseUrl_data()
13 | {
14 | QTest::addColumn("base");
15 | QTest::addColumn("version");
16 | QTest::addColumn("headers");
17 | QTest::addColumn("params");
18 | QTest::addColumn>("attributes");
19 | QTest::addColumn("sslConfig");
20 | QTest::addColumn("resultUrl");
21 |
22 | QUrlQuery query;
23 | query.addQueryItem("p1", "baum");
24 | query.addQueryItem("p2", "42");
25 | QHash attribs;
26 | attribs.insert(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
27 | auto config = QSslConfiguration::defaultConfiguration();
28 | config.setProtocol(QSsl::TlsV1_2);
29 | config.setPeerVerifyMode(QSslSocket::VerifyPeer);
30 | QTest::newRow("general") << QUrl("https://api.example.com/basic/")
31 | << QVersionNumber(4,2,0)
32 | << QtRestClient::HeaderHash({{"Bearer", "Secret"}})
33 | << query
34 | << attribs
35 | << config
36 | << QUrl("https://api.example.com/basic/v4.2?p1=baum&p2=42");
37 | }
38 |
39 | void RestClientTest::testBaseUrl()
40 | {
41 | QFETCH(QUrl, base);
42 | QFETCH(QVersionNumber, version);
43 | QFETCH(QtRestClient::HeaderHash, headers);
44 | QFETCH(QUrlQuery, params);
45 | auto attributes = *static_cast *>(QTest::qData("attributes", ::qMetaTypeId >::type>()));
46 | QFETCH(QSslConfiguration, sslConfig);
47 | QFETCH(QUrl, resultUrl);
48 |
49 | QtRestClient::RestClient client;
50 | client.setBaseUrl(base);
51 | client.setApiVersion(version);
52 | client.setGlobalHeaders(headers);
53 | client.setGlobalParameters(params);
54 | client.setRequestAttributes(attributes);
55 | client.setSslConfiguration(sslConfig);
56 |
57 | auto request = client.builder().build();
58 |
59 | QCOMPARE(request.url(), resultUrl);
60 | for(auto it = headers.constBegin(); it != headers.constEnd(); it++)
61 | QCOMPARE(request.rawHeader(it.key()), it.value());
62 | for(auto it = attributes.constBegin(); it != attributes.constEnd(); it++)
63 | QCOMPARE(request.attribute(it.key()), it.value());
64 | QCOMPARE(request.sslConfiguration(), sslConfig);
65 | }
66 |
67 | QTEST_MAIN(RestClientTest)
68 |
69 | #include "tst_restclient.moc"
70 |
--------------------------------------------------------------------------------
/src/imports/restclient/qmlrestreply.h:
--------------------------------------------------------------------------------
1 | #ifndef QTRESTCLIENT_QMLRESTREPLY_H
2 | #define QTRESTCLIENT_QMLRESTREPLY_H
3 |
4 | #include
5 |
6 | #include
7 |
8 | #include
9 | #include
10 |
11 | #ifdef DOXYGEN_RUN
12 | namespace de::skycoder42::QtRestClient {
13 |
14 | /*! @brief The QML version of ::QtRestClient::RestReply
15 | *
16 | * @extends QtQml.QtObject
17 | * @since 3.0
18 | *
19 | * This is a special version that is returned by the RestClass to be able to set handlers.
20 | * The original reply can be accessed via the RestReply::reply property.
21 | */
22 | class RestReply
23 | #else
24 | namespace QtRestClient {
25 |
26 | class QmlRestReply : public QObject
27 | #endif
28 | {
29 | Q_OBJECT
30 |
31 | /*! @brief The original ::QtRestClient::RestReply that this one wrapps
32 | *
33 | * @default{auto}
34 | * @accessors{
35 | * @memberAc{reply}
36 | * @readonlyAc
37 | * }
38 | * @sa ::QtRestClient::RestReply
39 | */
40 | Q_PROPERTY(QtRestClient::RestReply *reply MEMBER _reply CONSTANT)
41 |
42 | public:
43 | //! @private
44 | explicit QmlRestReply(RestReply *reply,
45 | QJSEngine *engine,
46 | QObject *parent = nullptr);
47 |
48 | public Q_SLOTS:
49 | /*! @brief Add a method to be called when the request has been completed
50 | *
51 | * @param completedHandler a JS callback to be called with the reply
52 | *
53 | * The handlers arguments are:
54 | * - The HTTP-Status code (int)
55 | */
56 | void addCompletedHandler(const QJSValue &completedHandler);
57 | /*! @brief Add a method to be called when the request has been completed successfully
58 | *
59 | * @param succeededHandler a JS callback to be called with the reply
60 | *
61 | * The handlers arguments are:
62 | * - The HTTP-Status code (int)
63 | * - The deserialized Content of the reply (deserialized to a JS object)
64 | */
65 | void addSucceededHandler(const QJSValue &succeededHandler);
66 | /*! @brief Add a method to be called if the request has failed
67 | *
68 | * @param failedHandler a JS callback to be called with the reply
69 | *
70 | * The handlers arguments are:
71 | * - The HTTP-Status code (int)
72 | * - The deserialized Content of the reply (deserialized to a JS object)
73 | */
74 | void addFailedHandler(const QJSValue &failedHandler);
75 | /*! @brief Add a method to be called if an error occured
76 | *
77 | * @param errorHandler a JS callback to be called with the reply
78 | *
79 | * The handlers arguments are:
80 | * - The error string (string)
81 | * - The error code (int)
82 | * - The error type (::QtRestClient::RestReply::Error)
83 | */
84 | void addErrorHandler(const QJSValue &errorHandler);
85 |
86 | private:
87 | QPointer _reply;
88 | QJSEngine *_engine;
89 |
90 | bool checkOk(const QJSValue &fn) const;
91 | };
92 |
93 | }
94 |
95 | #endif // QMLRESTREPLY_H
96 |
--------------------------------------------------------------------------------
/src/imports/restclient/qmlrestreply.cpp:
--------------------------------------------------------------------------------
1 | #include "qmlrestreply.h"
2 | #include
3 | #include
4 | using namespace QtRestClient;
5 |
6 | QmlRestReply::QmlRestReply(RestReply *reply, QJSEngine *engine, QObject *parent) :
7 | QObject{parent},
8 | _reply{reply},
9 | _engine{engine}
10 | {}
11 |
12 | void QmlRestReply::addCompletedHandler(const QJSValue &completedHandler)
13 | {
14 | if (!checkOk(completedHandler))
15 | return;
16 |
17 | _reply->onCompleted([completedHandler](int code){
18 | auto fn = completedHandler;
19 | fn.call({code});
20 | });
21 | }
22 |
23 | void QmlRestReply::addSucceededHandler(const QJSValue &succeededHandler)
24 | {
25 | if (!checkOk(succeededHandler))
26 | return;
27 |
28 | QPointer engine{_engine};
29 | QPointer reply{_reply};
30 |
31 | _reply->onSucceeded([this, succeededHandler, engine, reply](int code, const RestReply::DataType &data) {
32 | if (!engine)
33 | return;
34 | try {
35 | auto fn = succeededHandler;
36 | std::visit(__private::overload {
37 | [&](std::nullopt_t) {
38 | fn.call({code, QJSValue{}});
39 | },
40 | [&](const auto &vData) {
41 | fn.call({code, engine->toScriptValue(vData.toVariant())});
42 | }
43 | }, data);
44 | } catch (std::exception &e) {
45 | qmlWarning(this) << "ERROR:" << e.what();
46 | }
47 | });
48 | }
49 |
50 | void QmlRestReply::addFailedHandler(const QJSValue &failedHandler)
51 | {
52 | if (!checkOk(failedHandler))
53 | return;
54 |
55 | QPointer engine{_engine};
56 | QPointer reply{_reply};
57 |
58 | _reply->onFailed([this, failedHandler, engine, reply](int code, const RestReply::DataType &data) {
59 | if (!engine)
60 | return;
61 | try {
62 | auto fn = failedHandler;
63 | std::visit(__private::overload {
64 | [&](std::nullopt_t) {
65 | fn.call({code, QJSValue{}});
66 | },
67 | [&](const auto &vData) {
68 | fn.call({code, engine->toScriptValue(vData.toVariant())});
69 | }
70 | }, data);
71 | } catch (std::exception &e) {
72 | qmlWarning(this) << "ERROR:" << e.what();
73 | }
74 | });
75 | }
76 |
77 | void QmlRestReply::addErrorHandler(const QJSValue &errorHandler)
78 | {
79 | if (!checkOk(errorHandler))
80 | return;
81 |
82 | _reply->onError([errorHandler](const QString &error, int code, RestReply::Error type){
83 | auto fn = errorHandler;
84 | fn.call({error, code, static_cast(type)});
85 | });
86 | }
87 |
88 | bool QmlRestReply::checkOk(const QJSValue &fn) const
89 | {
90 | if (!_reply) {
91 | qmlWarning(this) << "Cannot assign a handler to an invalid reply";
92 | return false;
93 | }
94 |
95 | if (!fn.isCallable()) {
96 | qmlWarning(this) << "Passed JS object is not a callable function!";
97 | return false;
98 | }
99 |
100 | return true;
101 | }
102 |
--------------------------------------------------------------------------------
/doc/ipaging.dox:
--------------------------------------------------------------------------------
1 | /*!
2 | @class QtRestClient::IPaging
3 |
4 | Implement this interface, as well as a custom IPagingFactory, if you need to parse a non
5 | standard paging object. You should implement all of the methods correctly. However, you can
6 | still use the paging if you can't provide all of them. Simply return default values in that case.
7 | However, if you want to use the iterate functionality of the paging, you will have to implement
8 | all of them.
9 |
10 | The standard implementation expects CBOR or JSON data of the following format and will return
11 | either a ICborPaging or a IJsonPaging object:
12 | @code{.json}
13 | {
14 | "total": int,
15 | "offset": int,
16 | "limit": int,
17 | "previous": url|null,
18 | "next": url|null,
19 | "items": array
20 | }
21 | @endcode
22 |
23 | Additional fields will be ignored, but are still a valid paging objects. Missing fields or
24 | incompatibale types are not allowed, but wont create an error here. Validation is done by
25 | IPagingFactory::createPaging
26 |
27 | @sa ICborPaging, IJsonPaging, IPagingFactory, Paging
28 | */
29 |
30 | /*!
31 | @fn QtRestClient::IPaging::total
32 |
33 | @returns The total amount of items for this request, or `std::numeric_limits::max()` if not available
34 |
35 | If you implement total, please note that total means total independently of the paging, and **not**
36 | the number of elements in the paging. It's the maximum number of items that exist for this request on
37 | the server.
38 | */
39 |
40 | /*!
41 | @fn QtRestClient::IPaging::offset
42 |
43 | @returns The offset of the first item in the paging, or `-1` if not available
44 |
45 | Typically, pagings have indexes. However, since next() alone is sufficient to use a paging, not
46 | all may support it. Indexes means, that any item in a paging has a logical index, to identify it
47 | idependently of the paging object it is in. It's the real item index on the server. To do so,
48 | the offset of the first item in the paging must be known.
49 |
50 | If your paging does support indexes, you must implement the offset() method to return the offset
51 | of the first element in the paging.
52 | */
53 |
54 | /*!
55 | @class QtRestClient::IPagingFactory
56 |
57 | In order to use paging, you need a factory to create those. A default IPagingFactory
58 | is used to do so. However, if you need to reimplement IPaging, you need to create a factory
59 | as well.
60 |
61 | @sa IPaging, Paging, RestClient::pagingFactory
62 | */
63 |
64 | /*!
65 | @fn QtRestClient::IPagingFactory::createPaging
66 |
67 | @param serializer A json serializer, if you want to use it for deserialization
68 | @param data The paging CBOR/JSON data to be loaded into a IPaging interface
69 | @return A new paging interface instance
70 | @throws QJsonSerializer::DeserializationException Will be thrown if the passed json data is not
71 | a valid paging object
72 |
73 | When reimplementing this function, make shure to not return `nullptr`, if the creation failed.
74 | throw an exception instead, as specified by this documenation
75 | */
76 |
--------------------------------------------------------------------------------
/src/restclient/standardpaging_p.h:
--------------------------------------------------------------------------------
1 | #ifndef QTRESTCLIENT_STANDARDPAGING_P_H
2 | #define QTRESTCLIENT_STANDARDPAGING_P_H
3 |
4 | #include "QtRestClient/qtrestclient_global.h"
5 | #include "QtRestClient/ipaging.h"
6 |
7 | #include
8 | #include
9 |
10 | #include
11 |
12 | namespace QtRestClient {
13 |
14 | template
15 | class StandardPagingBase : public TPagingBase
16 | {
17 | static_assert (std::is_base_of_v, "TPagingBase must inherit or be the IPaging interface");
18 | friend class StandardPagingFactory;
19 | public:
20 | qint64 total() const override;
21 | qint64 offset() const override;
22 | bool hasNext() const override;
23 | QUrl next() const override;
24 | bool hasPrevious() const override;
25 | QUrl previous() const override;
26 |
27 | protected:
28 | qint64 _total = std::numeric_limits::max();
29 | qint64 _offset = -1;
30 | QUrl _prev;
31 | QUrl _next;
32 | };
33 |
34 | class Q_RESTCLIENT_EXPORT StandardCborPaging : public StandardPagingBase
35 | {
36 | friend class StandardPagingFactory;
37 | public:
38 | QVariantMap properties() const override;
39 | QCborArray cborItems() const override;
40 | QCborValue originalCbor() const override;
41 |
42 | private:
43 | QCborArray _items;
44 | QCborValue _data;
45 | };
46 |
47 | class Q_RESTCLIENT_EXPORT StandardJsonPaging : public StandardPagingBase
48 | {
49 | friend class StandardPagingFactory;
50 | public:
51 | QVariantMap properties() const override;
52 | QJsonArray jsonItems() const override;
53 | QJsonValue originalJson() const override;
54 |
55 | private:
56 | QJsonArray _items;
57 | QJsonValue _data;
58 | };
59 |
60 | class Q_RESTCLIENT_EXPORT StandardPagingFactory : public IPagingFactory
61 | {
62 | public:
63 | #ifndef Q_RESTCLIENT_NO_JSON_SERIALIZER
64 | IPaging *createPaging(QtJsonSerializer::SerializerBase *serializer, const std::variant &data) const override;
65 | #else
66 | IPaging *createPaging(const std::variant &data) const override;
67 | #endif
68 |
69 | private:
70 | static std::optional extractUrl(const std::variant &value);
71 | };
72 |
73 | // ------------- generic implementation -------------
74 |
75 | template
76 | qint64 StandardPagingBase::total() const
77 | {
78 | return _total;
79 | }
80 |
81 | template
82 | qint64 StandardPagingBase::offset() const
83 | {
84 | return _offset;
85 | }
86 |
87 | template
88 | bool StandardPagingBase::hasNext() const
89 | {
90 | return _next.isValid();
91 | }
92 |
93 | template
94 | QUrl StandardPagingBase::next() const
95 | {
96 | return _next;
97 | }
98 |
99 | template
100 | bool StandardPagingBase::hasPrevious() const
101 | {
102 | return _prev.isValid();
103 | }
104 |
105 | template
106 | QUrl StandardPagingBase::previous() const
107 | {
108 | return _prev;
109 | }
110 |
111 | }
112 |
113 | #endif // QTRESTCLIENT_STANDARDPAGING_P_H
114 |
--------------------------------------------------------------------------------
/src/restclient/ipaging.h:
--------------------------------------------------------------------------------
1 | #ifndef QTRESTCLIENT_IPAGING_H
2 | #define QTRESTCLIENT_IPAGING_H
3 |
4 | #include "QtRestClient/qtrestclient_global.h"
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #ifndef Q_RESTCLIENT_NO_JSON_SERIALIZER
14 | namespace QtJsonSerializer {
15 | class SerializerBase;
16 | }
17 | #endif
18 |
19 | namespace QtRestClient {
20 |
21 | //! Interface to parse generic paging objects and operate on them
22 | class Q_RESTCLIENT_EXPORT IPaging
23 | {
24 | Q_DISABLE_COPY(IPaging)
25 | public:
26 | IPaging();
27 | virtual ~IPaging();
28 |
29 | //! Returns the items of this paging object, i.e. it's data
30 | virtual std::variant items() const = 0;
31 |
32 | //! Returns the total number of objects there are
33 | virtual qint64 total() const;
34 | //! Returns the offset this paging begins at
35 | virtual qint64 offset() const;
36 | //! Returns true, if there is a next paging object
37 | virtual bool hasNext() const = 0;
38 | //! Returns the link to the next paging object
39 | virtual QUrl next() const = 0;
40 | //! Returns true, if there is a previous paging object
41 | virtual bool hasPrevious() const;
42 | //! Returns the link to the previous paging object
43 | virtual QUrl previous() const;
44 | //! Returns a hash containing all properties of the original JSON
45 | virtual QVariantMap properties() const = 0;
46 | //! Returns the original JSON element parsed
47 | virtual std::variant originalData() const = 0;
48 | };
49 |
50 | //! Interface to parse generic CBOR paging objects and operate on them
51 | class Q_RESTCLIENT_EXPORT ICborPaging : public IPaging
52 | {
53 | public:
54 | //! @copybrief IPaging::items
55 | virtual QCborArray cborItems() const = 0;
56 | //! @copybrief IPaging::originalData
57 | virtual QCborValue originalCbor() const = 0;
58 |
59 | std::variant items() const final;
60 | std::variant originalData() const final;
61 | };
62 |
63 | //! Interface to parse generic JSON paging objects and operate on them
64 | class Q_RESTCLIENT_EXPORT IJsonPaging : public IPaging
65 | {
66 | public:
67 | //! @copybrief IPaging::items
68 | virtual QJsonArray jsonItems() const = 0;
69 | //! @copybrief IPaging::originalData
70 | virtual QJsonValue originalJson() const = 0;
71 |
72 | std::variant items() const final;
73 | std::variant originalData() const final;
74 | };
75 |
76 | //! A factory interface to create IPaging instances from raw data
77 | class Q_RESTCLIENT_EXPORT IPagingFactory
78 | {
79 | Q_DISABLE_COPY(IPagingFactory)
80 |
81 | public:
82 | IPagingFactory();
83 | virtual ~IPagingFactory();
84 |
85 | //! Creates a new paging object of the given data
86 | #ifndef Q_RESTCLIENT_NO_JSON_SERIALIZER
87 | virtual IPaging *createPaging(QtJsonSerializer::SerializerBase *serializer, const std::variant &data) const = 0;
88 | #else
89 | virtual IPaging *createPaging(const std::variant &data) const = 0;
90 | #endif
91 | };
92 |
93 | }
94 |
95 | Q_DECLARE_METATYPE(QtRestClient::IPaging*)
96 |
97 | #endif // QTRESTCLIENT_IPAGING_H
98 |
--------------------------------------------------------------------------------
/tests/auto/testrun.pri:
--------------------------------------------------------------------------------
1 | debug_and_release:!ReleaseBuild:!DebugBuild {
2 | runtarget.target = run-tests
3 | runtarget.CONFIG = recursive
4 | runtarget.recurse_target = run-tests
5 | QMAKE_EXTRA_TARGETS += runtarget
6 | } else {
7 | oneshell.target = .ONESHELL
8 | QMAKE_EXTRA_TARGETS += oneshell
9 |
10 | win32:!win32-g++ {
11 | CONFIG(debug, debug|release): outdir_helper = debug
12 | CONFIG(release, debug|release): outdir_helper = release
13 | runtarget.target = run-tests
14 | !compat_test: runtarget.depends += $(DESTDIR_TARGET)
15 | runtarget.commands += set PATH=$$shell_path($$shadowed($$dirname(_QMAKE_CONF_))/bin);$$shell_path($$[QT_INSTALL_BINS]);$(PATH)
16 | runtarget.commands += $$escape_expand(\\n\\t)set QT_PLUGIN_PATH=$$shadowed($$dirname(_QMAKE_CONF_))/plugins;$$[QT_INSTALL_PLUGINS];$(QT_PLUGIN_PATH)
17 | runtarget.commands += $$escape_expand(\\n\\t)set QML2_IMPORT_PATH=$$shadowed($$dirname(_QMAKE_CONF_))/qml;$$[QT_INSTALL_QML];$(QML2_IMPORT_PATH)
18 | !isEmpty(LOGGING_RULES): runtarget.commands += $$escape_expand(\\n\\t)set \"QT_LOGGING_RULES=$$LOGGING_RULES\"
19 | runtarget.commands += $$escape_expand(\\n\\t)if exist $${outdir_helper}\\fail del $${outdir_helper}\\fail
20 | runtarget.commands += $$escape_expand(\\n\\t)start /w call $(DESTDIR_TARGET) ^> $${outdir_helper}\\test.log ^|^| echo FAIL ^> $${outdir_helper}\\fail ^& exit 0
21 | runtarget.commands += $$escape_expand(\\n\\t)type $${outdir_helper}\\test.log
22 | runtarget.commands += $$escape_expand(\\n\\t)if exist $${outdir_helper}\\fail exit 42
23 | QMAKE_EXTRA_TARGETS += runtarget
24 | } else {
25 | win32-g++: QMAKE_DIRLIST_SEP = ";"
26 | runtarget.commands += export PATH=\"$$shell_path($$shadowed($$dirname(_QMAKE_CONF_))/bin):$$shell_path($$[QT_INSTALL_BINS]):$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PATH\"
27 | runtarget.commands += $$escape_expand(\\n\\t)export QT_PLUGIN_PATH=\"$$shadowed($$dirname(_QMAKE_CONF_))/plugins$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_PLUGINS]$${QMAKE_DIRLIST_SEP}$(QT_PLUGIN_PATH)\"
28 | runtarget.commands += $$escape_expand(\\n\\t)export QML2_IMPORT_PATH=\"$$shadowed($$dirname(_QMAKE_CONF_))/qml$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_QML]$${QMAKE_DIRLIST_SEP}$(QML2_IMPORT_PATH)\"
29 | !isEmpty(LOGGING_RULES): runtarget.commands += $$escape_expand(\\n\\t)export QT_LOGGING_RULES=\"$$LOGGING_RULES\"
30 | win32-g++: QMAKE_DIRLIST_SEP = ":"
31 |
32 | linux|win32-g++ {
33 | runtarget.commands += $$escape_expand(\\n\\t)export LD_LIBRARY_PATH=\"$$shadowed($$dirname(_QMAKE_CONF_))/lib$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_LIBS]$${QMAKE_DIRLIST_SEP}$(LD_LIBRARY_PATH)\"
34 | runtarget.commands += $$escape_expand(\\n\\t)export QT_QPA_PLATFORM=minimal
35 | } else:mac {
36 | runtarget.commands += $$escape_expand(\\n\\t)export DYLD_LIBRARY_PATH=\"$$shadowed($$dirname(_QMAKE_CONF_))/lib:$$[QT_INSTALL_LIBS]:$(DYLD_LIBRARY_PATH)\"
37 | runtarget.commands += $$escape_expand(\\n\\t)export DYLD_FRAMEWORK_PATH=\"$$shadowed($$dirname(_QMAKE_CONF_))/lib:$$[QT_INSTALL_LIBS]:$(DYLD_FRAMEWORK_PATH)\"
38 | }
39 |
40 | runtarget.target = run-tests
41 | win32-g++ {
42 | !compat_test: runtarget.depends += $(DESTDIR_TARGET)
43 | runtarget.commands += $$escape_expand(\\n\\t)./$(DESTDIR_TARGET)
44 | } else {
45 | !compat_test: runtarget.depends += $(TARGET)
46 | runtarget.commands += $$escape_expand(\\n\\t)./$(TARGET)
47 | }
48 | QMAKE_EXTRA_TARGETS += runtarget
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/restclient/standardpaging.cpp:
--------------------------------------------------------------------------------
1 | #include "standardpaging_p.h"
2 | #include "qtrestclient_helpertypes.h"
3 | using namespace QtRestClient;
4 |
5 | #ifndef Q_RESTCLIENT_NO_JSON_SERIALIZER
6 | #include
7 | using namespace QtJsonSerializer;
8 | #endif
9 |
10 | QVariantMap StandardCborPaging::properties() const
11 | {
12 | return _data.toVariant().toMap();
13 | }
14 |
15 | QCborArray StandardCborPaging::cborItems() const
16 | {
17 | return _items;
18 | }
19 |
20 | QCborValue StandardCborPaging::originalCbor() const
21 | {
22 | return _data;
23 | }
24 |
25 | QVariantMap StandardJsonPaging::properties() const
26 | {
27 | return _data.toVariant().toMap();
28 | }
29 |
30 | QJsonArray StandardJsonPaging::jsonItems() const
31 | {
32 | return _items;
33 | }
34 |
35 | QJsonValue StandardJsonPaging::originalJson() const
36 | {
37 | return _data;
38 | }
39 |
40 | // ------------- Factory Implementation -------------
41 |
42 | #ifndef Q_RESTCLIENT_NO_JSON_SERIALIZER
43 | IPaging *StandardPagingFactory::createPaging(SerializerBase *, const std::variant &data) const
44 | #else
45 | IPaging *StandardPagingFactory::createPaging(const std::variant &data) const
46 | #endif
47 | {
48 | return std::visit(__private::overload {
49 | [](const QCborValue &value) -> IPaging* {
50 | const auto map = value.toMap();
51 | auto paging = new StandardCborPaging{};
52 | paging->_total = map[QStringLiteral("total")].toInteger(paging->_total);
53 | paging->_offset = map[QStringLiteral("offset")].toInteger(paging->_offset);
54 | if (const auto url = extractUrl(map[QStringLiteral("next")]); url)
55 | paging->_next = *url;
56 | if (const auto url = extractUrl(map[QStringLiteral("previous")]); url)
57 | paging->_prev = *url;
58 | paging->_items = map[QStringLiteral("items")].toArray();
59 | paging->_data = value;
60 | return paging;
61 | },
62 | [](const QJsonValue &value) -> IPaging* {
63 | const auto obj = value.toObject();
64 | auto paging = new StandardJsonPaging{};
65 | paging->_total = obj[QStringLiteral("total")].toInt(static_cast(paging->_total));
66 | paging->_offset = obj[QStringLiteral("offset")].toInt(static_cast(paging->_offset));
67 | if (const auto url = extractUrl(obj[QStringLiteral("next")]); url)
68 | paging->_next = *url;
69 | if (const auto url = extractUrl(obj[QStringLiteral("previous")]); url)
70 | paging->_prev = *url;
71 | paging->_items = obj[QStringLiteral("items")].toArray();
72 | paging->_data = value;
73 | return paging;
74 | }
75 | }, data);
76 | }
77 |
78 | std::optional StandardPagingFactory::extractUrl(const std::variant &value)
79 | {
80 | return std::visit(__private::overload {
81 | [](const QCborValue &data) -> std::optional {
82 | if (data.isUrl())
83 | return data.toUrl();
84 | else
85 | return std::nullopt;
86 | },
87 | [](const QJsonValue &data) -> std::optional {
88 | if (data.isString()) {
89 | QUrl url{data.toString()};
90 | if (url.isValid())
91 | return url;
92 | else
93 | return std::nullopt;
94 | } else
95 | return std::nullopt;
96 | }
97 | }, value);
98 | }
99 |
--------------------------------------------------------------------------------
/tools/qrestbuilder/main.cpp:
--------------------------------------------------------------------------------
1 | #include "classbuilder.h"
2 | #include "objectbuilder.h"
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #include "xmlconverter.h"
13 |
14 | //testing
15 | #include
16 |
17 | int main(int argc, char *argv[])
18 | {
19 | QCoreApplication a(argc, argv);
20 | QCoreApplication::setApplicationName(QStringLiteral(TARGET));
21 | QCoreApplication::setApplicationVersion(QStringLiteral(VERSION));
22 | QCoreApplication::setOrganizationName(QStringLiteral(COMPANY));
23 | QCoreApplication::setOrganizationDomain(QStringLiteral(BUNDLE_PREFIX));
24 |
25 | QCommandLineParser parser;
26 | parser.setApplicationDescription(QStringLiteral("A tool to create code for a rest API based on an API description"));
27 | parser.addVersionOption();
28 | parser.addHelpOption();
29 |
30 | parser.addOption({
31 | {QStringLiteral("c"), QStringLiteral("convert")},
32 | QStringLiteral("Convert a legacy json file of to the new XML format. "
33 | "Use --impl to specify the name of the RC-XML file to be created."),
34 | QStringLiteral("type")
35 | });
36 | parser.addOption({
37 | QStringLiteral("in"),
38 | QStringLiteral("The input JSON containing the API definition"),
39 | QStringLiteral("file")
40 | });
41 | parser.addOption({
42 | QStringLiteral("header"),
43 | QStringLiteral("The of the header file to generate"),
44 | QStringLiteral("name")
45 | });
46 | parser.addOption({
47 | QStringLiteral("impl"),
48 | QStringLiteral("The of the implementation file to generate"),
49 | QStringLiteral("name")
50 | });
51 |
52 | parser.process(a);
53 |
54 | try {
55 | if (parser.isSet(QStringLiteral("convert"))) {
56 | XmlConverter converter;
57 | converter.convert(parser.value(QStringLiteral("convert")),
58 | parser.value(QStringLiteral("in")),
59 | parser.value(QStringLiteral("impl")));
60 | return EXIT_SUCCESS;
61 | }
62 |
63 | QFile inFile(parser.value(QStringLiteral("in")));
64 | if(!inFile.open(QIODevice::ReadOnly | QIODevice::Text))
65 | throw RestBuilderXmlReader::FileException{inFile};
66 | QXmlStreamReader reader(&inFile);
67 |
68 | RestBuilderXmlReader builderBase;
69 | auto data = builderBase.readDocument(parser.value(QStringLiteral("in")));
70 |
71 | QScopedPointer builder;
72 | if (nonstd::holds_alternative(data))
73 | builder.reset(new ObjectBuilder(nonstd::get(data)));
74 | else if (nonstd::holds_alternative(data))
75 | builder.reset(new ObjectBuilder(nonstd::get