diff --git a/libnymea-core/jsonrpc/devicehandler.cpp b/libnymea-core/jsonrpc/devicehandler.cpp index 37429bee..69e749b1 100644 --- a/libnymea-core/jsonrpc/devicehandler.cpp +++ b/libnymea-core/jsonrpc/devicehandler.cpp @@ -443,7 +443,7 @@ JsonReply* DeviceHandler::GetPlugins(const QVariantMap ¶ms) const QVariantList plugins; foreach (DevicePlugin* plugin, NymeaCore::instance()->deviceManager()->plugins()) { - QVariantMap packedPlugin = pack(*plugin); + QVariantMap packedPlugin = pack(*plugin).toMap(); packedPlugin["displayName"] = NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), plugin->pluginDisplayName(), locale); plugins.append(packedPlugin); } @@ -904,7 +904,7 @@ QVariantMap DeviceHandler::packParamType(const ParamType ¶mType, const Plugi { ParamType translatedParamType = paramType; translatedParamType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(pluginId, paramType.displayName(), locale)); - return pack(translatedParamType); + return pack(translatedParamType).toMap(); } QVariantMap DeviceHandler::packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale) const diff --git a/libnymea/devices/device.cpp b/libnymea/devices/device.cpp index 5ed27594..f138181a 100644 --- a/libnymea/devices/device.cpp +++ b/libnymea/devices/device.cpp @@ -460,3 +460,14 @@ Devices Devices::filterByParentDeviceId(const DeviceId &deviceId) } return ret; } + +Devices Devices::filterByInterface(const QString &interface) +{ + Devices ret; + foreach (Device *device, *this) { + if (device->deviceClass().interfaces().indexOf(interface) >= 0) { + ret.append(device); + } + } + return ret; +} diff --git a/libnymea/devices/device.h b/libnymea/devices/device.h index 7a012b01..ac24b82b 100644 --- a/libnymea/devices/device.h +++ b/libnymea/devices/device.h @@ -161,6 +161,7 @@ public: Devices filterByParam(const ParamTypeId ¶mTypeId, const QVariant &value = QVariant()); Devices filterByDeviceClassId(const DeviceClassId &deviceClassId); Devices filterByParentDeviceId(const DeviceId &deviceId); + Devices filterByInterface(const QString &interface); }; Q_DECLARE_METATYPE(Device::DeviceError) diff --git a/libnymea/jsonrpc/jsonhandler.cpp b/libnymea/jsonrpc/jsonhandler.cpp index 4f5170e6..656d9e6f 100644 --- a/libnymea/jsonrpc/jsonhandler.cpp +++ b/libnymea/jsonrpc/jsonhandler.cpp @@ -140,73 +140,162 @@ JsonReply *JsonHandler::createAsyncReply(const QString &method) const return JsonReply::createAsyncReply(const_cast(this), method); } -QVariantMap JsonHandler::pack(const QMetaObject &metaObject, const void *value) const +QVariant JsonHandler::pack(const QMetaObject &metaObject, const void *value) const { - QVariantMap ret; -// qWarning() << "+ Packing" << metaObject.className(); - for (int i = 0; i < metaObject.propertyCount(); i++) { - QMetaProperty metaProperty = metaObject.property(i); - if (metaProperty.name() == QStringLiteral("objectName")) { - continue; // Skip QObject's objectName property + QString className = QString(metaObject.className()).split("::").last(); + if (m_listMetaObjects.contains(className)) { + QVariantList ret; + QMetaProperty countProperty = metaObject.property(metaObject.indexOfProperty("count")); + QMetaObject entryMetaObject = m_metaObjects.value(m_listEntryTypes.value(metaObject.className())); + int count = countProperty.readOnGadget(value).toInt(); + QMetaMethod getMethod = metaObject.method(metaObject.indexOfMethod("get(int)")); + for (int i = 0; i < count; i++) { + QVariant entry; + getMethod.invokeOnGadget(const_cast(value), Q_RETURN_ARG(QVariant, entry), Q_ARG(int, i)); + ret.append(pack(entryMetaObject, entry.data())); } + return ret; + } - QVariant val = metaProperty.readOnGadget(value); -// qWarning() << "|- Property:" << metaProperty.name() << metaProperty.readOnGadget(value) << metaProperty.type() << metaProperty.typeName(); -// qWarning() << "|-- All list types:" << m_listMetaObjects.keys(); - if (metaProperty.type() == QVariant::UserType) { + if (m_metaObjects.contains(className)) { + QVariantMap ret; + for (int i = 0; i < metaObject.propertyCount(); i++) { + QMetaProperty metaProperty = metaObject.property(i); + + // Skip QObject's objectName property + if (metaProperty.name() == QStringLiteral("objectName")) { + continue; + } + + // Pack flags + if (metaProperty.isFlagType()) { + QString flagName = QString(metaProperty.typeName()).split("::").last(); + Q_ASSERT_X(m_metaFlags.contains(flagName), this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered in this handler.").arg(className).arg(flagName).toUtf8()); + QMetaEnum metaFlag = m_metaFlags.value(flagName); + int flagValue = metaProperty.readOnGadget(value).toInt(); + QStringList flags; + for (int i = 0; i < metaFlag.keyCount(); i++) { + if ((metaFlag.value(i) & flagValue) > 0) { + flags.append(metaFlag.key(i)); + } + } + ret.insert(metaProperty.name(), flags); + continue; + } + + // Pack enums + if (metaProperty.isEnumType()) { + QString enumName = QString(metaProperty.typeName()).split("::").last(); + Q_ASSERT_X(m_metaEnums.contains(enumName), this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered in this handler.").arg(className).arg(metaProperty.typeName()).toUtf8()); + QMetaEnum metaEnum = m_metaEnums.value(enumName); + ret.insert(metaProperty.name(), metaEnum.key(metaProperty.readOnGadget(value).toInt())); + continue; + } + + // Basic type/Variant type if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) { QMetaEnum metaEnum = QMetaEnum::fromType(); -// qWarning() << "|--" << metaProperty.readOnGadget(value).toInt() << metaEnum.key(metaProperty.readOnGadget(value).toInt()); ret.insert(metaProperty.name(), metaEnum.key(variantTypeToBasicType(metaProperty.readOnGadget(value).template value()))); - } else if (m_listMetaObjects.contains(metaProperty.typeName())) { - QVariant listObject = metaProperty.readOnGadget(value); - QMetaObject listMetaObject = m_listMetaObjects.value(metaProperty.typeName()); - QMetaProperty countProperty = listMetaObject.property(listMetaObject.indexOfProperty("count")); - int listCount = countProperty.readOnGadget(listObject.constData()).toInt(); -// qWarning() << "Packing list type" << listObject << "count is" << listCount; - QMetaMethod metaMethod = listMetaObject.method(listMetaObject.indexOfMethod("get(int)")); -// qWarning() << "get method" << listMetaObject.indexOfMethod("get(int)") << listMetaObject.method(0).name() << QMetaObject::normalizedSignature("QVariant get(int)"); + continue; + } - QMetaObject entryMetaObject = m_metaObjects.value(m_listEntryTypes.value(listMetaObject.className())); - QVariantList list; - for (int i = 0; i < listCount; i++) { - QVariant entry; - metaMethod.invokeOnGadget(listObject.data(), Q_RETURN_ARG(QVariant, entry), Q_ARG(int, i)); -// qWarning() << "|---Feckin hell" << entry; - - list.append(pack(entryMetaObject, entry.data())); + // Our own objects + if (metaProperty.type() == QVariant::UserType) { + if (m_listMetaObjects.contains(metaProperty.typeName())) { + QMetaObject entryMetaObject = m_listMetaObjects.value(metaProperty.typeName()); + ret.insert(metaProperty.name(), pack(entryMetaObject, metaProperty.readOnGadget(value).data())); + continue; } - ret.insert(metaProperty.name(), list); - - - } else { - Q_ASSERT_X(false, this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered in this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8()); - } - } else if (metaProperty.isFlagType()) { - QMetaEnum metaFlag = m_metaFlags.value(QString(metaProperty.typeName()).split("::").last()); -// QMetaEnum metaEnum = m_metaEnums.value(m_flagsEnums.value(metaFlag.name())); - int flagValue = metaProperty.readOnGadget(value).toInt(); -// qWarning() << "|-- Flag" << flagValue << metaFlag.name() << metaFlag.keyCount() << metaProperty.type(); - QStringList flags; - for (int i = 0; i < metaFlag.keyCount(); i++) { -// qWarning() << "|--- flag key:" << metaFlag.key(i) << metaFlag.value(i); - if ((metaFlag.value(i) & flagValue) > 0) { - flags.append(metaFlag.key(i)); + if (m_metaObjects.contains(metaProperty.typeName())) { + QMetaObject entryMetaObject = m_metaObjects.value(metaProperty.typeName()); + ret.insert(metaProperty.name(), pack(entryMetaObject, metaProperty.readOnGadget(value).data())); + continue; } + + Q_ASSERT_X(false, this->metaObject()->className(), QString("Unregistered property type: %1").arg(metaProperty.typeName()).toUtf8()); + qCWarning(dcJsonRpc()) << "Cannot pack property of unregistered object type" << metaProperty.typeName(); + continue; } - ret.insert(metaProperty.name(), flags); - } else if (metaProperty.isEnumType()) { - QString enumName = QString(metaProperty.typeName()).split("::").last(); - Q_ASSERT_X(m_metaEnums.contains(enumName), this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered int this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8()); - QMetaEnum metaEnum = m_metaEnums.value(enumName); -// qWarning() << "|-- Enum: Name:" << metaEnum.name() << "as int:" << metaEnum.key(metaProperty.readOnGadget(value).toInt()) << "All enums:" << m_metaEnums.keys(); - ret.insert(metaProperty.name(), metaEnum.key(metaProperty.readOnGadget(value).toInt())); - } else if (!metaProperty.isUser() || !metaProperty.readOnGadget(value).isNull()) { -// qWarning() << "|-- property" << metaProperty.name() << metaProperty.readOnGadget(value); - ret.insert(metaProperty.name(), metaProperty.readOnGadget(value)); + + // Standard properties, QString, int etc... If it's not optional, or if it's not empty, pack it up + if (!metaProperty.isUser() || !metaProperty.readOnGadget(value).isNull()) { + ret.insert(metaProperty.name(), metaProperty.readOnGadget(value)); + } + } + return ret; } - return ret; + + Q_ASSERT_X(false, this->metaObject()->className(), QString("Unregistered object type: %1").arg(className).toUtf8()); + qCWarning(dcJsonRpc()) << "Cannot pack object of unregistered type" << className; + return QVariant(); +// QVariantMap ret; +//// qWarning() << "+ Packing" << metaObject.className(); +// for (int i = 0; i < metaObject.propertyCount(); i++) { +// QMetaProperty metaProperty = metaObject.property(i); +// if (metaProperty.name() == QStringLiteral("objectName")) { +// continue; // Skip QObject's objectName property +// } + +// QVariant val = metaProperty.readOnGadget(value); +//// qWarning() << "|- Property:" << metaProperty.name() << metaProperty.readOnGadget(value) << metaProperty.type() << metaProperty.typeName(); +//// qWarning() << "|-- All list types:" << m_listMetaObjects.keys(); +// if (metaProperty.type() == QVariant::UserType) { +// if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) { +// QMetaEnum metaEnum = QMetaEnum::fromType(); +//// qWarning() << "|--" << metaProperty.readOnGadget(value).toInt() << metaEnum.key(metaProperty.readOnGadget(value).toInt()); +// ret.insert(metaProperty.name(), metaEnum.key(variantTypeToBasicType(metaProperty.readOnGadget(value).template value()))); +// } else if (m_listMetaObjects.contains(metaProperty.typeName())) { +// QVariant listObject = metaProperty.readOnGadget(value); +// QMetaObject listMetaObject = m_listMetaObjects.value(metaProperty.typeName()); +// QMetaProperty countProperty = listMetaObject.property(listMetaObject.indexOfProperty("count")); +// int listCount = countProperty.readOnGadget(listObject.constData()).toInt(); +//// qWarning() << "Packing list type" << listObject << "count is" << listCount; +// QMetaMethod metaMethod = listMetaObject.method(listMetaObject.indexOfMethod("get(int)")); +//// qWarning() << "get method" << listMetaObject.indexOfMethod("get(int)") << listMetaObject.method(0).name() << QMetaObject::normalizedSignature("QVariant get(int)"); + +// QMetaObject entryMetaObject = m_metaObjects.value(m_listEntryTypes.value(listMetaObject.className())); +// QVariantList list; +// for (int i = 0; i < listCount; i++) { +// QVariant entry; +// metaMethod.invokeOnGadget(listObject.data(), Q_RETURN_ARG(QVariant, entry), Q_ARG(int, i)); +//// qWarning() << "|---Feckin hell" << entry; + +// list.append(pack(entryMetaObject, entry.data())); +// } + +// ret.insert(metaProperty.name(), list); + + +// } else { +// Q_ASSERT_X(false, this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered in this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8()); +// } +// } else if (metaProperty.isFlagType()) { +// QMetaEnum metaFlag = m_metaFlags.value(QString(metaProperty.typeName()).split("::").last()); +//// QMetaEnum metaEnum = m_metaEnums.value(m_flagsEnums.value(metaFlag.name())); +// int flagValue = metaProperty.readOnGadget(value).toInt(); +//// qWarning() << "|-- Flag" << flagValue << metaFlag.name() << metaFlag.keyCount() << metaProperty.type(); +// QStringList flags; +// for (int i = 0; i < metaFlag.keyCount(); i++) { +//// qWarning() << "|--- flag key:" << metaFlag.key(i) << metaFlag.value(i); +// if ((metaFlag.value(i) & flagValue) > 0) { +// flags.append(metaFlag.key(i)); +// } +// } +// ret.insert(metaProperty.name(), flags); +// } else if (metaProperty.isEnumType()) { +// QString enumName = QString(metaProperty.typeName()).split("::").last(); +// Q_ASSERT_X(m_metaEnums.contains(enumName), this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered int this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8()); +// QMetaEnum metaEnum = m_metaEnums.value(enumName); +//// qWarning() << "|-- Enum: Name:" << metaEnum.name() << "as int:" << metaEnum.key(metaProperty.readOnGadget(value).toInt()) << "All enums:" << m_metaEnums.keys(); +// ret.insert(metaProperty.name(), metaEnum.key(metaProperty.readOnGadget(value).toInt())); +// } else if (!metaProperty.isUser() || !metaProperty.readOnGadget(value).isNull()) { +//// qWarning() << "|-- property" << metaProperty.name() << metaProperty.readOnGadget(value); +// ret.insert(metaProperty.name(), metaProperty.readOnGadget(value)); +// } +// } +// return ret; + } diff --git a/libnymea/jsonrpc/jsonhandler.h b/libnymea/jsonrpc/jsonhandler.h index 87423f64..289df8a7 100644 --- a/libnymea/jsonrpc/jsonhandler.h +++ b/libnymea/jsonrpc/jsonhandler.h @@ -49,7 +49,8 @@ public: static BasicType variantTypeToBasicType(QVariant::Type variantType); static QVariant::Type basicTypeToVariantType(BasicType basicType); - template QVariantMap pack(const T &value) const; + template QVariant pack(const T &value) const; + template T unpack(const QVariantMap &map) const; protected: template void registerEnum(); @@ -64,7 +65,7 @@ protected: JsonReply *createAsyncReply(const QString &method) const; private: - QVariantMap pack(const QMetaObject &metaObject, const void *gadget) const; + QVariant pack(const QMetaObject &metaObject, const void *gadget) const; private: QVariantMap m_enums; @@ -189,11 +190,35 @@ T JsonHandler::enumNameToValue(const QString &name) } template -QVariantMap JsonHandler::pack(const T &value) const +QVariant JsonHandler::pack(const T &value) const { QMetaObject metaObject = T::staticMetaObject; return pack(metaObject, static_cast(&value)); } +template +T JsonHandler::unpack(const QVariantMap &map) const +{ + T ret; + QMetaObject metaObject = T::staticMetaObject; + for (int i = 0; i < metaObject.propertyCount(); i++) { + QMetaProperty metaProperty = metaObject.property(i); + if (metaProperty.name() == QStringLiteral("objectName")) { + continue; + } + if (!metaProperty.isWritable()) { + continue; + } + if (!metaProperty.isUser()) { + Q_ASSERT_X(map.contains(metaProperty.name()), this->metaObject()->className(), QString("Missing property %1 in map.").arg(metaProperty.name()).toUtf8()); + } + if (map.contains(metaProperty.name())) { + metaProperty.writeOnGadget(&ret, map.value(metaProperty.name())); + } + } + return ret; +} + + #endif // JSONHANDLER_H diff --git a/libnymea/time/calendaritem.cpp b/libnymea/time/calendaritem.cpp index edee90bb..ee39e1ee 100644 --- a/libnymea/time/calendaritem.cpp +++ b/libnymea/time/calendaritem.cpp @@ -274,3 +274,18 @@ QDebug operator<<(QDebug dbg, const CalendarItem &calendarItem) } + +CalendarItems::CalendarItems() +{ + +} + +CalendarItems::CalendarItems(const QList &other): QList(other) +{ + +} + +QVariant CalendarItems::get(int index) +{ + return QVariant::fromValue(at(index)); +} diff --git a/libnymea/time/calendaritem.h b/libnymea/time/calendaritem.h index 56eb6341..4d2b5534 100644 --- a/libnymea/time/calendaritem.h +++ b/libnymea/time/calendaritem.h @@ -24,6 +24,7 @@ #include #include "repeatingoption.h" +#include class CalendarItem { @@ -66,6 +67,17 @@ private: }; +class CalendarItems: public QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + CalendarItems(); + CalendarItems(const QList &other); + Q_INVOKABLE QVariant get(int index); +}; +Q_DECLARE_METATYPE(CalendarItems) + QDebug operator<<(QDebug dbg, const CalendarItem &calendarItem); #endif // CALENDARITEM_H