Browse Source

generic injection prepared

pull/2/head
Skycoder42 7 years ago
parent
commit
f1d751f1ae
  1. 1
      examples/mvvmcore/SampleCore/ieventservice.h
  2. 30
      examples/mvvmwidgets/SampleWidgets/main.cpp
  3. 13
      examples/mvvmwidgets/SampleWidgets/widgetseventservice.cpp
  4. 1
      examples/mvvmwidgets/SampleWidgets/widgetseventservice.h
  5. 2
      src/mvvmcore/qtmvvmcore_global.h
  6. 79
      src/mvvmcore/qtmvvmcore_helpertypes.h
  7. 2
      src/mvvmcore/serviceregistry.cpp
  8. 79
      src/mvvmcore/serviceregistry.h
  9. 2
      src/mvvmquick/qtmvvmquick_global.h
  10. 2
      src/mvvmwidgets/qtmvvmwidgets_global.h

1
examples/mvvmcore/SampleCore/ieventservice.h

@ -15,5 +15,6 @@ Q_SIGNALS:
#define IEventServiceIid "de.skycoder42.qtmvvm.sample.IEventService"
Q_DECLARE_INTERFACE(IEventService, IEventServiceIid)
Q_DECLARE_METATYPE(IEventService*)
#endif // IEVENTSERVICE_H

30
examples/mvvmwidgets/SampleWidgets/main.cpp

@ -1,9 +1,39 @@
#include "mainwindow.h"
#include <QApplication>
#include <QtMvvmCore/ServiceRegistry>
#include "widgetseventservice.h"
struct test : public QObject {
IEventService *i;
EchoService *s;
test(IEventService *i, EchoService *s) :
i(i),
s(s)
{}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtMvvm::ServiceRegistry::instance()->registerObject<EchoService>();
if (false) {
QtMvvm::ServiceRegistry::instance()->registerObject<EchoService>([]() {
return new EchoService(nullptr);
});
QtMvvm::ServiceRegistry::instance()->registerObject<EchoService>(new EchoService());
}
QtMvvm::ServiceRegistry::instance()->registerInterface<IEventService, WidgetsEventService>();
if (false) {
QtMvvm::ServiceRegistry::instance()->registerInterface<IEventService, WidgetsEventService>([](EchoService *echo) {
return new WidgetsEventService(echo, nullptr);
});
QtMvvm::ServiceRegistry::instance()->registerInterface<IEventService>(new WidgetsEventService());
}
return a.exec();
}

13
examples/mvvmwidgets/SampleWidgets/widgetseventservice.cpp

@ -4,7 +4,16 @@ WidgetsEventService::WidgetsEventService(QObject *parent) :
QObject(parent),
IEventService(),
_cnt(0),
_events()
_events(),
_echoService(nullptr)
{}
WidgetsEventService::WidgetsEventService(EchoService *svc, QObject *parent) :
QObject(parent),
IEventService(),
_cnt(0),
_events(),
_echoService(svc)
{}
int WidgetsEventService::addEvent(const QString &name)
@ -16,7 +25,7 @@ int WidgetsEventService::addEvent(const QString &name)
_events.insert(_cnt, timer);
connect(timer.data(), &QTimer::timeout, this, [this, name]() {
emit eventTriggered(name);
_echoService->ping(name);//TODO event triggered signal
});
timer->start(1000);

1
examples/mvvmwidgets/SampleWidgets/widgetseventservice.h

@ -19,6 +19,7 @@ class WidgetsEventService : public QObject, public IEventService
public:
explicit WidgetsEventService(QObject *parent = nullptr);
explicit WidgetsEventService(EchoService* svc, QObject *parent = nullptr);
int addEvent(const QString &name) override;
void removeEvent(int eventId) override;

2
src/mvvmcore/qtmvvmcore_global.h

@ -5,7 +5,7 @@
#include "qtmvvmcore_helpertypes.h"
#if defined(QT_BUILD_MVVM_LIB)
#if defined(QT_BUILD_MVVMCORE_LIB)
# define Q_MVVMCORE_EXPORT Q_DECL_EXPORT
#else
# define Q_MVVMCORE_EXPORT Q_DECL_IMPORT

79
src/mvvmcore/qtmvvmcore_helpertypes.h

@ -2,35 +2,96 @@
#define QTMVVMCORE_HELPERTYPES_H
#include <type_traits>
#include <tuple>
#include <functional>
#include <QtCore/qobject.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qvariant.h>
namespace QtMvvm {
namespace __helpertypes {
#if __cplusplus >= 201703L
template<typename... T>
using conjunction = std::conjunction<T...>;
#else
template<typename... T>
using conjunction = std::__and_<T...>;
#endif
static const QByteArray InjectablePrefix = QByteArrayLiteral("de.skycoder42.qtmvvm.injectable.");
template <typename T>
struct is_qobj : public std::is_base_of<QObject, T> {};
template <typename T>
struct is_qobj : public std::is_base_of<QObject, std::remove_pointer_t<T>> {};
struct is_qobj_ptr : public is_qobj<std::remove_pointer_t<T>> {};
template <typename TInject>
inline QByteArray qobject_iid(std::enable_if_t<is_qobj<TInject>::value, void*> = nullptr) {
return QByteArrayLiteral("de.skycoder42.qtmvvm.injectable.") + std::remove_pointer_t<TInject>::staticMetaObject.className();
template <typename TInterface, typename TService>
struct is_valid_interface : public conjunction<std::is_base_of<TInterface, TService>, is_qobj<TService>> {};
template <typename TInjectPtr>
inline QByteArray qobject_iid(std::enable_if_t<is_qobj_ptr<TInjectPtr>::value, void*> = nullptr) {
return InjectablePrefix + std::remove_pointer_t<TInjectPtr>::staticMetaObject.className();
}
template <typename TInject>
inline QByteArray qobject_iid(std::enable_if_t<!is_qobj<TInject>::value, void*> = nullptr) {
template <typename TInjectPtr>
inline QByteArray qobject_iid(std::enable_if_t<!is_qobj_ptr<TInjectPtr>::value, void*> = nullptr) {
Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid injection type");
return "";
}
template <typename TInject>
template <typename TInjectPtr>
inline QByteArray inject_iid() {
auto iid = qobject_interface_iid<TInject>();
auto iid = qobject_interface_iid<TInjectPtr>();
if(iid)
return iid;
else
return qobject_iid<TInject>();
return qobject_iid<TInjectPtr>();
}
template <typename TFunc, typename T1, typename... TArgs>
inline Q_CONSTEXPR std::function<QObject*(QVariantList)> pack_function_imp(const TFunc &fn, QByteArrayList &injectables) {
injectables.append(inject_iid<T1>());
auto subFn = [fn](const QVariantList &params, int index, TArgs... tArgs) {
--index;
return fn(params, index, params[index].template value<T1>(), tArgs...);
};
return pack_function_imp<decltype(subFn), TArgs...>(subFn, injectables);
}
template <typename TFunc>
inline Q_CONSTEXPR std::function<QObject*(QVariantList)> pack_function_imp(const TFunc &fn, QByteArrayList &injectables) {
Q_UNUSED(injectables)
return [fn](const QVariantList &params) {
return fn(params, params.size());
};
}
template <typename T>
struct fn_info : public fn_info<decltype(&T::operator())> {};
template <typename TClass, typename TRet, typename... TArgs>
struct fn_info<TRet(TClass::*)(TArgs...) const>
{
template <typename TFunctor>
static inline Q_CONSTEXPR std::function<QObject*(QVariantList)> pack(const TFunctor &fn, QByteArrayList &injectables) {
auto subFn = [fn](const QVariantList &params, int index, TArgs... args) -> QObject* {
Q_UNUSED(params)
Q_ASSERT_X(index == 0, Q_FUNC_INFO, "number of params does not equal recursion depth");
return fn(args...);
};
return pack_function_imp<decltype(subFn), TArgs...>(subFn, injectables);
}
};
template <typename TFunc>
inline Q_CONSTEXPR std::function<QObject*(QVariantList)> pack_function(const TFunc &fn, QByteArrayList &injectables) {
return fn_info<TFunc>::pack(fn, injectables);
}
}
}

2
src/mvvmcore/serviceregistry.cpp

@ -19,7 +19,7 @@ ServiceRegistry *ServiceRegistry::instance()
void ServiceRegistry::registerService(const QByteArray &iid, const QMetaObject *metaObject)
{
//TODO create function with injectables and pass to other overload
}
void ServiceRegistry::registerService(const QByteArray &iid, const std::function<QObject *(const QVariantList &)> &fn, QByteArrayList injectables)

79
src/mvvmcore/serviceregistry.h

@ -4,6 +4,7 @@
#include <functional>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qvariant.h>
#include "QtMvvmCore/qtmvvmcore_global.h"
@ -18,17 +19,17 @@ public:
static ServiceRegistry* instance();
template <typename TInterface, typename TService>
void registerService();
template <typename TInterface, typename TService, typename... Injectables>
void registerService(const std::function<TService*(Injectables...)> &fn);
void registerInterface();
template <typename TInterface, typename TService, typename TFunc>
void registerInterface(const TFunc &fn);
template <typename TInterface, typename TService>
void registerService(TService *service);
void registerInterface(TService *service);
template <typename TService>
void registerService();
template <typename TService, typename... Injectables>
void registerService(const std::function<TService*(Injectables...)> &fn);
void registerObject();
template <typename TService, typename TFunc>
void registerObject(const TFunc &fn);
template <typename TService>
void registerService(TService *service);
void registerObject(TService *service);
void registerService(const QByteArray &iid,
const QMetaObject *metaObject);
@ -40,6 +41,68 @@ private:
QScopedPointer<ServiceRegistryPrivate> d;
};
#define QTMVVM_SERVICE_ASSERT(tint, tsvc) \
static_assert(__helpertypes::is_valid_interface<TInterface, TService>::value, "TService must implement the given TInterface interface and be a qobject class"); \
Q_ASSERT_X(qobject_interface_iid<TInterface*>(), Q_FUNC_INFO, "TInterface must be registered with Q_DECLARE_INTERFACE");
template<typename TInterface, typename TService>
void ServiceRegistry::registerInterface()
{
QTMVVM_SERVICE_ASSERT(TInterface, TService)
registerService(qobject_interface_iid<TInterface*>(), &TService::staticMetaObject);
}
template <typename TInterface, typename TService, typename TFunc>
void ServiceRegistry::registerInterface(const TFunc &fn)
{
QTMVVM_SERVICE_ASSERT(TInterface, TService)
QByteArrayList injectables;
auto packed_fn = __helpertypes::pack_function(fn, injectables);
registerService(qobject_interface_iid<TInterface*>(), packed_fn, injectables);
}
template<typename TInterface, typename TService>
void ServiceRegistry::registerInterface(TService *service)
{
QTMVVM_SERVICE_ASSERT(TInterface, TService)
registerService(qobject_interface_iid<TInterface*>(), [service](const QVariantList &params) -> QObject* {
Q_UNUSED(params);
return service;
}, QByteArrayList());
}
#undef QTMVVM_SERVICE_ASSERT
#define QTMVVM_SERVICE_ASSERT(tsvc) \
static_assert(__helpertypes::is_qobj<tsvc>::value, "TService must be a qobject class");
template<typename TService>
void ServiceRegistry::registerObject()
{
QTMVVM_SERVICE_ASSERT(TService)
registerService(__helpertypes::qobject_iid<TService*>(), &TService::staticMetaObject);
}
template<typename TService, typename TFunc>
void ServiceRegistry::registerObject(const TFunc &fn)
{
QTMVVM_SERVICE_ASSERT(TService)
QByteArrayList injectables;
auto packed_fn = __helpertypes::pack_function(fn, injectables);
registerService(__helpertypes::qobject_iid<TService*>(), packed_fn, injectables);
}
template<typename TService>
void ServiceRegistry::registerObject(TService *service)
{
QTMVVM_SERVICE_ASSERT(TService)
registerService(__helpertypes::qobject_iid<TService*>(), [service](const QVariantList &params) -> QObject* {
Q_UNUSED(params);
return service;
}, QByteArrayList());
}
#undef QTMVVM_SERVICE_ASSERT
}
#endif // QTMVVM_SERVICEREGISTRY_H

2
src/mvvmquick/qtmvvmquick_global.h

@ -3,7 +3,7 @@
#include <QtCore/qglobal.h>
#if defined(QT_BUILD_MVVM_LIB)
#if defined(QT_BUILD_MVVMQUICK_LIB)
# define Q_MVVMQUICK_EXPORT Q_DECL_EXPORT
#else
# define Q_MVVMQUICK_EXPORT Q_DECL_IMPORT

2
src/mvvmwidgets/qtmvvmwidgets_global.h

@ -3,7 +3,7 @@
#include <QtCore/qglobal.h>
#if defined(QT_BUILD_MVVM_LIB)
#if defined(QT_BUILD_MVVMWIDGETS_LIB)
# define Q_MVVMWIDGETS_EXPORT Q_DECL_EXPORT
#else
# define Q_MVVMWIDGETS_EXPORT Q_DECL_IMPORT

Loading…
Cancel
Save