forked from quickshell/quickshell
		
	dbus/properties: support data transformation/validation before store
This commit is contained in:
		
							parent
							
								
									a13c9d91b5
								
							
						
					
					
						commit
						d4deb11216
					
				
					 2 changed files with 83 additions and 18 deletions
				
			
		| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <functional>
 | 
					#include <functional>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
#include <utility>
 | 
					#include <utility>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <bit>
 | 
					#include <bit>
 | 
				
			||||||
| 
						 | 
					@ -43,7 +44,7 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool isValid() { return !this->error.isValid(); }
 | 
						bool isValid() { return !this->error.isValid(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	T value;
 | 
						T value {};
 | 
				
			||||||
	QDBusError error;
 | 
						QDBusError error;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -137,6 +138,16 @@ private:
 | 
				
			||||||
	friend class DBusPropertyGroup;
 | 
						friend class DBusPropertyGroup;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Default implementation with no transformation
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					struct DBusDataTransform {
 | 
				
			||||||
 | 
						using Wire = T;
 | 
				
			||||||
 | 
						using Data = T;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static DBusResult<Data> fromWire(Wire&& wire) { return DBusResult<T>(std::move(wire)); }
 | 
				
			||||||
 | 
						static Wire toWire(const Data& value) { return value; }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace bindable_p {
 | 
					namespace bindable_p {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <typename T>
 | 
					template <typename T>
 | 
				
			||||||
| 
						 | 
					@ -149,9 +160,16 @@ struct BindableParams<B<C, T, O, S>> {
 | 
				
			||||||
	static constexpr size_t OFFSET = O;
 | 
						static constexpr size_t OFFSET = O;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename Bindable>
 | 
				
			||||||
 | 
					struct BindableType {
 | 
				
			||||||
 | 
						using Meta = BindableParams<Bindable>;
 | 
				
			||||||
 | 
						using Type = Meta::Type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace bindable_p
 | 
					} // namespace bindable_p
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <
 | 
					template <
 | 
				
			||||||
 | 
					    typename T,
 | 
				
			||||||
    auto offset,
 | 
					    auto offset,
 | 
				
			||||||
    auto bindablePtr,
 | 
					    auto bindablePtr,
 | 
				
			||||||
    auto updatedPtr,
 | 
					    auto updatedPtr,
 | 
				
			||||||
| 
						 | 
					@ -160,10 +178,13 @@ template <
 | 
				
			||||||
    bool required>
 | 
					    bool required>
 | 
				
			||||||
class DBusBindableProperty: public DBusPropertyCore {
 | 
					class DBusBindableProperty: public DBusPropertyCore {
 | 
				
			||||||
	using PtrMeta = MemberPointerTraits<decltype(bindablePtr)>;
 | 
						using PtrMeta = MemberPointerTraits<decltype(bindablePtr)>;
 | 
				
			||||||
	using Bindable = PtrMeta::Type;
 | 
					 | 
				
			||||||
	using Owner = PtrMeta::Class;
 | 
						using Owner = PtrMeta::Class;
 | 
				
			||||||
	using BindableMeta = bindable_p::BindableParams<Bindable>;
 | 
						using Bindable = PtrMeta::Type;
 | 
				
			||||||
	using DataType = BindableMeta::Type;
 | 
						using BindableType = bindable_p::BindableType<Bindable>::Type;
 | 
				
			||||||
 | 
						using BaseType = std::conditional_t<std::is_void_v<T>, BindableType, T>;
 | 
				
			||||||
 | 
						using Transform = DBusDataTransform<BaseType>;
 | 
				
			||||||
 | 
						using DataType = Transform::Data;
 | 
				
			||||||
 | 
						using WireType = Transform::Wire;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	explicit DBusBindableProperty() { this->group()->attachProperty(this); }
 | 
						explicit DBusBindableProperty() { this->group()->attachProperty(this); }
 | 
				
			||||||
| 
						 | 
					@ -183,20 +204,33 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
	QDBusError store(const QVariant& variant) override {
 | 
						QDBusError store(const QVariant& variant) override {
 | 
				
			||||||
		auto result = demarshallVariant<DataType>(variant);
 | 
							DBusResult<DataType> result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (result.isValid()) {
 | 
							if constexpr (std::is_same_v<WireType, BaseType>) {
 | 
				
			||||||
			this->bindable()->setValue(std::move(result.value));
 | 
								result = demarshallVariant<DataType>(variant);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
			if constexpr (updatedPtr != nullptr) {
 | 
								auto wireResult = demarshallVariant<WireType>(variant);
 | 
				
			||||||
				(this->owner()->*updatedPtr)();
 | 
								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<WireType, BaseType>) {
 | 
				
			||||||
 | 
								return QVariant::fromValue(this->bindable()->value());
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return QVariant::fromValue(Transform::toWire(this->bindable()->value()));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	[[nodiscard]] constexpr Owner* owner() const {
 | 
						[[nodiscard]] constexpr Owner* owner() const {
 | 
				
			||||||
| 
						 | 
					@ -308,10 +342,20 @@ private:
 | 
				
			||||||
// NOLINTBEGIN
 | 
					// NOLINTBEGIN
 | 
				
			||||||
#define QS_DBUS_BINDABLE_PROPERTY_GROUP(Class, name) qs::dbus::DBusPropertyGroup name {this};
 | 
					#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); } \
 | 
						static constexpr size_t _qs_property_##property##_offset() { return offsetof(Class, property); } \
 | 
				
			||||||
                                                                                                   \
 | 
					                                                                                                   \
 | 
				
			||||||
	qs::dbus::DBusBindableProperty<                                                                  \
 | 
						qs::dbus::DBusBindableProperty<                                                                  \
 | 
				
			||||||
 | 
						    Type,                                                                                        \
 | 
				
			||||||
	    &Class::_qs_property_##property##_offset,                                                    \
 | 
						    &Class::_qs_property_##property##_offset,                                                    \
 | 
				
			||||||
	    &Class::bindable,                                                                            \
 | 
						    &Class::bindable,                                                                            \
 | 
				
			||||||
	    updated,                                                                                     \
 | 
						    updated,                                                                                     \
 | 
				
			||||||
| 
						 | 
					@ -320,11 +364,32 @@ private:
 | 
				
			||||||
	    required>                                                                                    \
 | 
						    required>                                                                                    \
 | 
				
			||||||
	    property;
 | 
						    property;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define QS_DBUS_PROPERTY_BINDING_7(Class, property, bindable, updated, group, name, required)      \
 | 
					#define QS_DBUS_PROPERTY_BINDING_8(                                                                \
 | 
				
			||||||
	QS_DBUS_PROPERTY_BINDING_P(Class, property, bindable, &Class::updated, group, name, required)
 | 
					    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)               \
 | 
					#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)                         \
 | 
					#define QS_DBUS_PROPERTY_BINDING_5(Class, property, bindable, group, name)                         \
 | 
				
			||||||
	QS_DBUS_PROPERTY_BINDING_6(Class, property, bindable, group, name, true)
 | 
						QS_DBUS_PROPERTY_BINDING_6(Class, property, bindable, group, name, true)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -457,7 +457,7 @@ private:
 | 
				
			||||||
	QS_DBUS_PROPERTY_BINDING(MprisPlayer, pCanSeek, bpCanSeek, playerProperties, "CanSeek");
 | 
						QS_DBUS_PROPERTY_BINDING(MprisPlayer, pCanSeek, bpCanSeek, playerProperties, "CanSeek");
 | 
				
			||||||
	QS_DBUS_PROPERTY_BINDING(MprisPlayer, pCanGoNext, bpCanGoNext, playerProperties, "CanGoNext");
 | 
						QS_DBUS_PROPERTY_BINDING(MprisPlayer, pCanGoNext, bpCanGoNext, playerProperties, "CanGoNext");
 | 
				
			||||||
	QS_DBUS_PROPERTY_BINDING(MprisPlayer, pCanGoPrevious, bpCanGoPrevious, playerProperties, "CanGoPrevious");
 | 
						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, pVolume, bVolume, playerProperties, "Volume", false);
 | 
				
			||||||
	QS_DBUS_PROPERTY_BINDING(MprisPlayer, pMetadata, bpMetadata, playerProperties, "Metadata");
 | 
						QS_DBUS_PROPERTY_BINDING(MprisPlayer, pMetadata, bpMetadata, playerProperties, "Metadata");
 | 
				
			||||||
	QS_DBUS_PROPERTY_BINDING(MprisPlayer, pPlaybackStatus, bpPlaybackStatus, playerProperties, "PlaybackStatus");
 | 
						QS_DBUS_PROPERTY_BINDING(MprisPlayer, pPlaybackStatus, bpPlaybackStatus, playerProperties, "PlaybackStatus");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue