#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../core/util.hpp" class DBusPropertiesInterface; Q_DECLARE_LOGGING_CATEGORY(logDbusProperties); namespace qs::dbus { QDBusError demarshallVariant(const QVariant& variant, const QMetaType& type, void* slot); template class DBusResult { public: explicit DBusResult() = default; explicit DBusResult(T value): value(std::move(value)) {} explicit DBusResult(QDBusError error): error(std::move(error)) {} explicit DBusResult(T value, QDBusError error) : value(std::move(value)) , error(std::move(error)) {} bool isValid() { return !this->error.isValid(); } T value {}; QDBusError error; }; template DBusResult demarshallVariant(const QVariant& variant) { T value; auto error = demarshallVariant(variant, QMetaType::fromType(), &value); return DBusResult(value, error); } void asyncReadPropertyInternal( const QMetaType& type, QDBusAbstractInterface& interface, const QString& property, std::function)> callback ); template void asyncReadProperty( QDBusAbstractInterface& interface, const QString& property, std::function callback ) { asyncReadPropertyInternal( QMetaType::fromType(), interface, property, [callback](std::function internalCallback) { // NOLINT T slot; auto error = internalCallback(static_cast(&slot)); callback(slot, error); } ); } class DBusPropertyGroup; class DBusPropertyCore { public: DBusPropertyCore() = default; virtual ~DBusPropertyCore() = default; Q_DISABLE_COPY_MOVE(DBusPropertyCore); [[nodiscard]] virtual QString name() const = 0; [[nodiscard]] virtual QStringView nameRef() const = 0; [[nodiscard]] virtual QString valueString() = 0; [[nodiscard]] virtual bool isRequired() const = 0; [[nodiscard]] bool exists() const { return this->mExists; } protected: virtual QDBusError store(const QVariant& variant) = 0; [[nodiscard]] virtual QVariant serialize() = 0; private: bool mExists : 1 = false; friend class DBusPropertyGroup; }; class AbstractDBusProperty : public QObject , public DBusPropertyCore { Q_OBJECT; public: explicit AbstractDBusProperty(QString name, bool required, QObject* parent = nullptr) : QObject(parent) , required(required) , mName(std::move(name)) {} [[nodiscard]] QString name() const override { return this->mName; }; [[nodiscard]] QStringView nameRef() const override { return this->mName; }; [[nodiscard]] bool isRequired() const override { return this->required; }; [[nodiscard]] QString toString() const; public slots: void update(); void write(); signals: void changed(); private: bool required : 1; bool mExists : 1 = false; DBusPropertyGroup* group = nullptr; QString mName; friend class DBusPropertyGroup; }; // Default implementation with no transformation template struct DBusDataTransform { using Wire = T; using Data = T; }; namespace bindable_p { template struct BindableParams; template