From d4deb11216ddecfaeb6f7739b9c4aed9447b7aeb Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Thu, 21 Nov 2024 03:27:52 -0800 Subject: [PATCH] dbus/properties: support data transformation/validation before store --- src/dbus/properties.hpp | 99 +++++++++++++++++++++++++++++------ src/services/mpris/player.hpp | 2 +- 2 files changed, 83 insertions(+), 18 deletions(-) diff --git a/src/dbus/properties.hpp b/src/dbus/properties.hpp index 11e7e063..9fe5a873 100644 --- a/src/dbus/properties.hpp +++ b/src/dbus/properties.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -43,7 +44,7 @@ public: bool isValid() { return !this->error.isValid(); } - T value; + T value {}; QDBusError error; }; @@ -137,6 +138,16 @@ private: friend class DBusPropertyGroup; }; +// Default implementation with no transformation +template +struct DBusDataTransform { + using Wire = T; + using Data = T; + + static DBusResult fromWire(Wire&& wire) { return DBusResult(std::move(wire)); } + static Wire toWire(const Data& value) { return value; } +}; + namespace bindable_p { template @@ -149,9 +160,16 @@ struct BindableParams> { static constexpr size_t OFFSET = O; }; +template +struct BindableType { + using Meta = BindableParams; + using Type = Meta::Type; +}; + } // namespace bindable_p template < + typename T, auto offset, auto bindablePtr, auto updatedPtr, @@ -160,10 +178,13 @@ template < bool required> class DBusBindableProperty: public DBusPropertyCore { using PtrMeta = MemberPointerTraits; - using Bindable = PtrMeta::Type; using Owner = PtrMeta::Class; - using BindableMeta = bindable_p::BindableParams; - using DataType = BindableMeta::Type; + using Bindable = PtrMeta::Type; + using BindableType = bindable_p::BindableType::Type; + using BaseType = std::conditional_t, BindableType, T>; + using Transform = DBusDataTransform; + using DataType = Transform::Data; + using WireType = Transform::Wire; public: explicit DBusBindableProperty() { this->group()->attachProperty(this); } @@ -183,20 +204,33 @@ public: protected: QDBusError store(const QVariant& variant) override { - auto result = demarshallVariant(variant); + DBusResult result; - if (result.isValid()) { - this->bindable()->setValue(std::move(result.value)); - - if constexpr (updatedPtr != nullptr) { - (this->owner()->*updatedPtr)(); - } + if constexpr (std::is_same_v) { + result = demarshallVariant(variant); + } else { + auto wireResult = demarshallVariant(variant); + if (!wireResult.isValid()) return wireResult.error; + result = Transform::fromWire(std::move(wireResult.value)); } - return result.error; + if (!result.isValid()) return result.error; + this->bindable()->setValue(std::move(result.value)); + + if constexpr (updatedPtr != nullptr) { + (this->owner()->*updatedPtr)(); + } + + return QDBusError(); } - QVariant serialize() override { return QVariant::fromValue(this->bindable()->value()); } + QVariant serialize() override { + if constexpr (std::is_same_v) { + return QVariant::fromValue(this->bindable()->value()); + } else { + return QVariant::fromValue(Transform::toWire(this->bindable()->value())); + } + } private: [[nodiscard]] constexpr Owner* owner() const { @@ -308,10 +342,20 @@ private: // NOLINTBEGIN #define QS_DBUS_BINDABLE_PROPERTY_GROUP(Class, name) qs::dbus::DBusPropertyGroup name {this}; -#define QS_DBUS_PROPERTY_BINDING_P(Class, property, bindable, updated, group, name, required) \ +#define QS_DBUS_PROPERTY_BINDING_P( \ + Class, \ + Type, \ + property, \ + bindable, \ + updated, \ + group, \ + name, \ + required \ +) \ static constexpr size_t _qs_property_##property##_offset() { return offsetof(Class, property); } \ \ qs::dbus::DBusBindableProperty< \ + Type, \ &Class::_qs_property_##property##_offset, \ &Class::bindable, \ updated, \ @@ -320,11 +364,32 @@ private: required> \ property; -#define QS_DBUS_PROPERTY_BINDING_7(Class, property, bindable, updated, group, name, required) \ - QS_DBUS_PROPERTY_BINDING_P(Class, property, bindable, &Class::updated, group, name, required) +#define QS_DBUS_PROPERTY_BINDING_8( \ + Class, \ + Type, \ + property, \ + bindable, \ + updated, \ + group, \ + name, \ + required \ +) \ + QS_DBUS_PROPERTY_BINDING_P( \ + Class, \ + Type, \ + property, \ + bindable, \ + &Class::updated, \ + group, \ + name, \ + required \ + ) + +#define QS_DBUS_PROPERTY_BINDING_7(Class, Type, property, bindable, group, name, required) \ + QS_DBUS_PROPERTY_BINDING_P(Class, Type, property, bindable, nullptr, group, name, required) #define QS_DBUS_PROPERTY_BINDING_6(Class, property, bindable, group, name, required) \ - QS_DBUS_PROPERTY_BINDING_P(Class, property, bindable, nullptr, group, name, required) + QS_DBUS_PROPERTY_BINDING_7(Class, void, property, bindable, group, name, required) #define QS_DBUS_PROPERTY_BINDING_5(Class, property, bindable, group, name) \ QS_DBUS_PROPERTY_BINDING_6(Class, property, bindable, group, name, true) diff --git a/src/services/mpris/player.hpp b/src/services/mpris/player.hpp index b08dee8e..eb030dca 100644 --- a/src/services/mpris/player.hpp +++ b/src/services/mpris/player.hpp @@ -457,7 +457,7 @@ private: QS_DBUS_PROPERTY_BINDING(MprisPlayer, pCanSeek, bpCanSeek, playerProperties, "CanSeek"); QS_DBUS_PROPERTY_BINDING(MprisPlayer, pCanGoNext, bpCanGoNext, playerProperties, "CanGoNext"); QS_DBUS_PROPERTY_BINDING(MprisPlayer, pCanGoPrevious, bpCanGoPrevious, playerProperties, "CanGoPrevious"); - QS_DBUS_PROPERTY_BINDING(MprisPlayer, pPosition, bpPosition, onPositionUpdated, playerProperties, "Position", false); + QS_DBUS_PROPERTY_BINDING(MprisPlayer, qlonglong, pPosition, bpPosition, onPositionUpdated, playerProperties, "Position", false); QS_DBUS_PROPERTY_BINDING(MprisPlayer, pVolume, bVolume, playerProperties, "Volume", false); QS_DBUS_PROPERTY_BINDING(MprisPlayer, pMetadata, bpMetadata, playerProperties, "Metadata"); QS_DBUS_PROPERTY_BINDING(MprisPlayer, pPlaybackStatus, bpPlaybackStatus, playerProperties, "PlaybackStatus");