feat: LogosResult (#14)

* Add LogosResult

* Add documentation for complex types

* Add get type util function

* Add more shorthand functions

* Add bool support

* Provide more shorthand functions

* Throw exception on bad access

* Fix typo in doc
This commit is contained in:
Arnaud
2026-02-25 09:13:43 -05:00
committed by GitHub
parent 30ef7986f4
commit 4fdf157120
10 changed files with 297 additions and 5 deletions
+3
View File
@@ -11,6 +11,8 @@ find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core RemoteObjects)
# SDK sources
set(SDK_SOURCES
logos_types.cpp
logos_types.h
logos_api.cpp
logos_api.h
logos_api_client.cpp
@@ -52,6 +54,7 @@ install(TARGETS logos_sdk
# Install headers
install(FILES
logos_types.h
logos_api.h
logos_api_client.h
logos_api_consumer.h
+1
View File
@@ -55,6 +55,7 @@ echo "Generating MOC files..."
# List of headers that need MOC processing (contain Q_OBJECT)
MOC_HEADERS=(
"logos_types.h"
"logos_api.h"
"logos_api_client.h"
"logos_api_provider.h"
+5
View File
@@ -14,12 +14,17 @@ LogosAPI::LogosAPI(const QString& module_name, QObject *parent)
// Get token manager instance
m_token_manager = &TokenManager::instance();
// Register LogosResult as QVariant type
qRegisterMetaType<LogosResult>("LogosResult");
}
LogosAPI::~LogosAPI()
{
// Provider and client will be automatically deleted as child objects
// Token manager is a singleton, so we don't delete it
}
LogosAPIProvider* LogosAPI::getProvider() const
+2 -1
View File
@@ -4,6 +4,7 @@
#include <QObject>
#include <QString>
#include <QHash>
#include "logos_types.h"
class LogosAPIClient;
class LogosAPIProvider;
@@ -57,4 +58,4 @@ private:
TokenManager* m_token_manager;
};
#endif // LOGOS_API_H
#endif // LOGOS_API_H
+11
View File
@@ -0,0 +1,11 @@
#include "logos_types.h"
QDataStream& operator<<(QDataStream& out, const LogosResult& result) {
out << result.success << result.value;
return out;
}
QDataStream& operator>>(QDataStream& in, LogosResult& result) {
in >> result.success >> result.value;
return in;
}
+138
View File
@@ -0,0 +1,138 @@
#ifndef LOGOS_TYPES_H
#define LOGOS_TYPES_H
#include <QDataStream>
#include <QVariant>
#include <stdexcept>
class LogosResultException : public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
};
struct LogosResult
{
bool success;
// Error message if success is false
// Value can be retrieved like this:
//
// LogosResult result = someMethod();
// if (result.success) {
// QString someValue = result.getValue<QString>();
// // OR
// QString someValue = result.getString();
// }
QVariant value;
// LogosResult result = someMethod();
// if (!result.success) {
// QString error = result.getError();
// }
QVariant error;
template<typename T = QString>
T getError() const
{
if (success) {
throw LogosResultException("Attempted to get error from a successful LogosResult");
}
return error.value<T>();
}
template<typename T>
T getValue() const
{
if (!success) {
throw LogosResultException("Attempted to get value from a failed LogosResult: "
+ error.toString().toStdString());
}
return value.value<T>();
}
template<typename T>
T getValue(const QString &key, T defaultValue = T()) const
{
const QVariantMap &map = getValue<QVariantMap>();
if (!map.contains(key)) {
return defaultValue;
}
return qvariant_cast<T>(map.value(key));
}
template<typename T>
T getValue(int index, const QString &key, T defaultValue = T()) const
{
const QVariantList &list = getValue<QVariantList>();
if (index < 0 || index >= list.size()) {
return defaultValue;
}
return qvariant_cast<T>(list[index].toMap().value(key, defaultValue));
}
QString getString() const { return getValue<QString>(); }
QString getString(const QString &key, const QString &defaultValue = "") const
{
return getValue<QString>(key, defaultValue);
}
QString getString(int index, const QString &key, const QString &defaultValue = "") const
{
return getValue<QString>(index, key, defaultValue);
}
bool getBool() const { return getValue<bool>(); }
bool getBool(const QString &key) const { return getValue<bool>(key); }
bool getBool(int index, const QString &key) const { return getValue<bool>(index, key); }
int getInt() const { return getValue<int>(); }
int getInt(const QString &key, int defaultValue = 0) const
{
return getValue<int>(key, defaultValue);
}
int getInt(int index, const QString &key, int defaultValue = 0) const
{
return getValue<int>(index, key, defaultValue);
}
QVariantList getList() const { return getValue<QVariantList>(); }
QVariantList getList(const QString &key, const QVariantList &defaultValue = QVariantList()) const
{
return getValue<QVariantList>(key, defaultValue);
}
QVariantList getList(int index,
const QString &key,
const QVariantList &defaultValue = QVariantList()) const
{
return getValue<QVariantList>(index, key, defaultValue);
}
QVariantMap getMap() const { return getValue<QVariantMap>(); }
QVariantMap getMap(const QString &key, const QVariantMap &defaultValue = QVariantMap()) const
{
return getValue<QVariantMap>(key, defaultValue);
}
QVariantMap getMap(int index,
const QString &key,
const QVariantMap &defaultValue = QVariantMap()) const
{
return getValue<QVariantMap>(index, key, defaultValue);
}
};
// Provide (de)serialisation for being use as Remote Object
QDataStream &operator<<(QDataStream &out, const LogosResult &result);
QDataStream &operator>>(QDataStream &in, LogosResult &result);
#endif
+23 -2
View File
@@ -94,7 +94,7 @@ namespace {
);
break;
}
case QMetaType::QUrl: {
case QMetaType::QUrl: {
auto value = new QUrl{arg.toUrl()};
scopedArgs.emplace_back(
Q_ARG(QUrl, *value),
@@ -104,6 +104,16 @@ namespace {
);
break;
}
case QMetaType::Bool: {
auto value = new bool{arg.toBool()};
scopedArgs.emplace_back(
Q_ARG(bool, *value),
[](const void* data) {
delete static_cast<const bool*>(data);
}
);
break;
}
case QMetaType::QString:
default: {
auto value = new QString{arg.toString()};
@@ -155,6 +165,8 @@ namespace {
INVOKE_METHOD_WITH_RETURN(int, int);
} else if (strcmp(returnTypeName, "QString") == 0) {
INVOKE_METHOD_WITH_RETURN(QString, QString);
} else if (strcmp(returnTypeName, "LogosResult") == 0) {
INVOKE_METHOD_WITH_RETURN(LogosResult, LogosResult);
} else if (strcmp(returnTypeName, "QVariant") == 0) {
INVOKE_METHOD_WITH_RETURN(QVariant, QVariant);
} else if (strcmp(returnTypeName, "QJsonArray") == 0) {
@@ -344,7 +356,16 @@ QVariant ModuleProxy::callRemoteMethod(const QString& authToken, const QString&
if (success) {
result = QVariant(stringResult);
}
} else if (returnType == QMetaType::fromType<QVariant>()) {
}
else if (returnType == QMetaType::fromType<LogosResult>()) {
// LogosResult return type
LogosResult logosResult;
success = invokeMethodByArgCount(m_module, methodName, args, &logosResult, "LogosResult");
if (success) {
result = QVariant::fromValue(logosResult);
}
}
else if (returnType == QMetaType::fromType<QVariant>()) {
// QVariant return type
QVariant variantResult;
success = invokeMethodByArgCount(m_module, methodName, args, &variantResult, "QVariant");