Browse Source

.

pull/2/head
Skycoder42 7 years ago
parent
commit
40c0c98a02
  1. 27
      examples/mvvmwidgets/SampleWidgets/main.cpp
  2. 16
      src/mvvmcore/qtmvvmcore_helpertypes.h
  3. 81
      src/mvvmcore/serviceregistry.cpp
  4. 6
      src/mvvmcore/serviceregistry.h
  5. 42
      src/mvvmcore/serviceregistry_p.h

27
examples/mvvmwidgets/SampleWidgets/main.cpp

@ -5,35 +5,32 @@
#include "widgetseventservice.h" #include "widgetseventservice.h"
struct test : public QObject { #define TEST_DIRECT 0
IEventService *i; #define TEST_FN 1
EchoService *s; #define TEST_INST 2
#define TEST_CURRENT TEST_DIRECT
test(IEventService *i, EchoService *s) :
i(i),
s(s)
{}
};
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication a(argc, argv); QApplication a(argc, argv);
QtMvvm::ServiceRegistry::instance()->registerObject<EchoService>(); if(TEST_CURRENT == TEST_DIRECT)
if (false) { QtMvvm::ServiceRegistry::instance()->registerObject<EchoService>();
if(TEST_CURRENT == TEST_FN)
QtMvvm::ServiceRegistry::instance()->registerObject<EchoService>([]() { QtMvvm::ServiceRegistry::instance()->registerObject<EchoService>([]() {
return new EchoService(nullptr); return new EchoService(nullptr);
}); });
if(TEST_CURRENT == TEST_INST)
QtMvvm::ServiceRegistry::instance()->registerObject<EchoService>(new EchoService()); QtMvvm::ServiceRegistry::instance()->registerObject<EchoService>(new EchoService());
}
QtMvvm::ServiceRegistry::instance()->registerInterface<IEventService, WidgetsEventService>(); if(TEST_CURRENT == TEST_DIRECT)
if (false) { QtMvvm::ServiceRegistry::instance()->registerInterface<IEventService, WidgetsEventService>();
if(TEST_CURRENT == TEST_FN)
QtMvvm::ServiceRegistry::instance()->registerInterface<IEventService, WidgetsEventService>([](EchoService *echo) { QtMvvm::ServiceRegistry::instance()->registerInterface<IEventService, WidgetsEventService>([](EchoService *echo) {
return new WidgetsEventService(echo, nullptr); return new WidgetsEventService(echo, nullptr);
}); });
if(TEST_CURRENT == TEST_INST)
QtMvvm::ServiceRegistry::instance()->registerInterface<IEventService>(new WidgetsEventService()); QtMvvm::ServiceRegistry::instance()->registerInterface<IEventService>(new WidgetsEventService());
}
return a.exec(); return a.exec();
} }

16
src/mvvmcore/qtmvvmcore_helpertypes.h

@ -52,19 +52,19 @@ inline QByteArray inject_iid() {
} }
template <typename TFunc, typename T1, typename... TArgs> template <typename TFunc, typename T1, typename... TArgs>
inline Q_CONSTEXPR std::function<QObject*(QVariantList)> pack_function_imp(const TFunc &fn, QByteArrayList &injectables) { inline Q_CONSTEXPR std::function<QObject*(QObjectList)> pack_function_imp(const TFunc &fn, QByteArrayList &injectables) {
injectables.append(inject_iid<T1>()); injectables.append(inject_iid<T1>());
auto subFn = [fn](const QVariantList &params, int index, TArgs... tArgs) { auto subFn = [fn](const QObjectList &params, int index, TArgs... tArgs) {
--index; --index;
return fn(params, index, params[index].template value<T1>(), tArgs...); return fn(params, index, qobject_cast<T1>(params[index]), tArgs...);
}; };
return pack_function_imp<decltype(subFn), TArgs...>(subFn, injectables); return pack_function_imp<decltype(subFn), TArgs...>(subFn, injectables);
} }
template <typename TFunc> template <typename TFunc>
inline Q_CONSTEXPR std::function<QObject*(QVariantList)> pack_function_imp(const TFunc &fn, QByteArrayList &injectables) { inline Q_CONSTEXPR std::function<QObject*(QObjectList)> pack_function_imp(const TFunc &fn, QByteArrayList &injectables) {
Q_UNUSED(injectables) Q_UNUSED(injectables)
return [fn](const QVariantList &params) { return [fn](const QObjectList &params) {
return fn(params, params.size()); return fn(params, params.size());
}; };
} }
@ -76,8 +76,8 @@ template <typename TClass, typename TRet, typename... TArgs>
struct fn_info<TRet(TClass::*)(TArgs...) const> struct fn_info<TRet(TClass::*)(TArgs...) const>
{ {
template <typename TFunctor> template <typename TFunctor>
static inline Q_CONSTEXPR std::function<QObject*(QVariantList)> pack(const TFunctor &fn, QByteArrayList &injectables) { static inline Q_CONSTEXPR std::function<QObject*(QObjectList)> pack(const TFunctor &fn, QByteArrayList &injectables) {
auto subFn = [fn](const QVariantList &params, int index, TArgs... args) -> QObject* { auto subFn = [fn](const QObjectList &params, int index, TArgs... args) -> QObject* {
Q_UNUSED(params) Q_UNUSED(params)
Q_ASSERT_X(index == 0, Q_FUNC_INFO, "number of params does not equal recursion depth"); Q_ASSERT_X(index == 0, Q_FUNC_INFO, "number of params does not equal recursion depth");
return fn(args...); return fn(args...);
@ -87,7 +87,7 @@ struct fn_info<TRet(TClass::*)(TArgs...) const>
}; };
template <typename TFunc> template <typename TFunc>
inline Q_CONSTEXPR std::function<QObject*(QVariantList)> pack_function(const TFunc &fn, QByteArrayList &injectables) { inline Q_CONSTEXPR std::function<QObject*(QObjectList)> pack_function(const TFunc &fn, QByteArrayList &injectables) {
return fn_info<TFunc>::pack(fn, injectables); return fn_info<TFunc>::pack(fn, injectables);
} }

81
src/mvvmcore/serviceregistry.cpp

@ -2,6 +2,8 @@
#include "serviceregistry_p.h" #include "serviceregistry_p.h"
#include <QtCore/QGlobalStatic> #include <QtCore/QGlobalStatic>
#include <QtCore/QRegularExpression>
#include <QtCore/QMetaProperty>
using namespace QtMvvm; using namespace QtMvvm;
@ -19,17 +21,88 @@ ServiceRegistry *ServiceRegistry::instance()
void ServiceRegistry::registerService(const QByteArray &iid, const QMetaObject *metaObject) void ServiceRegistry::registerService(const QByteArray &iid, const QMetaObject *metaObject)
{ {
//TODO create function with injectables and pass to other overload QMutexLocker _(&d->serviceMutex);
Q_ASSERT(!d->services.contains(iid)); //TODO exception
d->services.insert(iid, QSharedPointer<ServiceRegistryPrivate::MetaServiceInfo>::create(metaObject));
} }
void ServiceRegistry::registerService(const QByteArray &iid, const std::function<QObject *(const QVariantList &)> &fn, QByteArrayList injectables) void ServiceRegistry::registerService(const QByteArray &iid, const std::function<QObject*(const QObjectList &)> &fn, QByteArrayList injectables)
{ {
QMutexLocker _(&d->serviceMutex);
Q_ASSERT(!d->services.contains(iid)); //TODO exception
d->services.insert(iid, QSharedPointer<ServiceRegistryPrivate::FnServiceInfo>::create(fn, injectables));
} }
// ------------- Private Implementation ------------- // ------------- Private Implementation -------------
ServiceRegistryPrivate::ServiceRegistryPrivate() ServiceRegistryPrivate::ServiceRegistryPrivate() :
serviceMutex(),
services()
{}
ServiceRegistryPrivate::ServiceInfo::ServiceInfo() :
_instance(nullptr)
{}
ServiceRegistryPrivate::ServiceInfo::~ServiceInfo()
{
if(_instance)
QMetaObject::invokeMethod(_instance, "deleteLater");
}
QObject *ServiceRegistryPrivate::ServiceInfo::instance(ServiceRegistryPrivate *d)
{
if(!_instance)
_instance = construct(d);
return _instance;
}
ServiceRegistryPrivate::FnServiceInfo::FnServiceInfo(const std::function<QObject*(QObjectList)> &creator, const QByteArrayList &injectables) :
creator(creator),
injectables(injectables)
{}
QObject *ServiceRegistryPrivate::FnServiceInfo::construct(ServiceRegistryPrivate *d) const
{
QObjectList params;
foreach(auto inj, injectables)
params.append(d->services.value(inj)->instance(d));//TODO exception
return creator(params);
}
ServiceRegistryPrivate::MetaServiceInfo::MetaServiceInfo(const QMetaObject *metaObject) :
metaObject(metaObject)
{}
QObject *ServiceRegistryPrivate::MetaServiceInfo::construct(ServiceRegistryPrivate *d) const
{ {
auto instance = metaObject->newInstance();
Q_ASSERT(instance); //TODO exception
static QRegularExpression nameRegex(QStringLiteral(R"__(^__qtmvvm_inject_(.+)$)__"),
QRegularExpression::OptimizeOnFirstUsageOption);
for(auto i = 0; i < metaObject->propertyCount(); i++) {
auto prop = metaObject->property(i);
auto match = nameRegex.match(QString::fromUtf8(prop.name()));
if(match.hasMatch()) {
auto tPropIndex = metaObject->indexOfProperty(qUtf8Printable(match.captured(1)));
if(tPropIndex == -1)
continue; //TODO warning
auto tProp = metaObject->property(tPropIndex);
auto inject = prop.read(instance).toByteArray();
auto injObj = d->services.value(inject)->instance(d); //TODO exception
tProp.write(instance, QVariant::fromValue(injObj)); //TODO check if casting works
}
}
//TODO call "init" method
return instance;
} }

6
src/mvvmcore/serviceregistry.h

@ -34,7 +34,7 @@ public:
void registerService(const QByteArray &iid, void registerService(const QByteArray &iid,
const QMetaObject *metaObject); const QMetaObject *metaObject);
void registerService(const QByteArray &iid, void registerService(const QByteArray &iid,
const std::function<QObject*(const QVariantList&)> &fn, const std::function<QObject*(const QObjectList &)> &fn,
QByteArrayList injectables); QByteArrayList injectables);
private: private:
@ -65,7 +65,7 @@ template<typename TInterface, typename TService>
void ServiceRegistry::registerInterface(TService *service) void ServiceRegistry::registerInterface(TService *service)
{ {
QTMVVM_SERVICE_ASSERT(TInterface, TService) QTMVVM_SERVICE_ASSERT(TInterface, TService)
registerService(qobject_interface_iid<TInterface*>(), [service](const QVariantList &params) -> QObject* { registerService(qobject_interface_iid<TInterface*>(), [service](const QObjectList &params) -> QObject* {
Q_UNUSED(params); Q_UNUSED(params);
return service; return service;
}, QByteArrayList()); }, QByteArrayList());
@ -95,7 +95,7 @@ template<typename TService>
void ServiceRegistry::registerObject(TService *service) void ServiceRegistry::registerObject(TService *service)
{ {
QTMVVM_SERVICE_ASSERT(TService) QTMVVM_SERVICE_ASSERT(TService)
registerService(__helpertypes::qobject_iid<TService*>(), [service](const QVariantList &params) -> QObject* { registerService(__helpertypes::qobject_iid<TService*>(), [service](const QObjectList &params) -> QObject* {
Q_UNUSED(params); Q_UNUSED(params);
return service; return service;
}, QByteArrayList()); }, QByteArrayList());

42
src/mvvmcore/serviceregistry_p.h

@ -1,6 +1,8 @@
#ifndef QTMVVM_SERVICEREGISTRY_P_H #ifndef QTMVVM_SERVICEREGISTRY_P_H
#define QTMVVM_SERVICEREGISTRY_P_H #define QTMVVM_SERVICEREGISTRY_P_H
#include <QtCore/QMutex>
#include "qtmvvmcore_global.h" #include "qtmvvmcore_global.h"
#include "serviceregistry.h" #include "serviceregistry.h"
@ -9,6 +11,46 @@ namespace QtMvvm {
class ServiceRegistryPrivate class ServiceRegistryPrivate
{ {
public: public:
class ServiceInfo {
public:
ServiceInfo();
virtual ~ServiceInfo();
QObject *instance(ServiceRegistryPrivate *d);
protected:
virtual QObject *construct(ServiceRegistryPrivate *d) const = 0;
private:
QObject *_instance;
};
class FnServiceInfo : public ServiceInfo {
public:
FnServiceInfo(const std::function<QObject*(QObjectList)> &creator, const QByteArrayList &injectables);
protected:
QObject *construct(ServiceRegistryPrivate *d) const final;
private:
std::function<QObject*(QObjectList)> creator;
QByteArrayList injectables;
};
class MetaServiceInfo : public ServiceInfo {
public:
MetaServiceInfo(const QMetaObject *metaObject);
protected:
QObject *construct(ServiceRegistryPrivate *d) const final;
private:
const QMetaObject *metaObject;
};
QMutex serviceMutex;
QHash<QByteArray, QSharedPointer<ServiceInfo>> services;
ServiceRegistryPrivate(); ServiceRegistryPrivate();
}; };

Loading…
Cancel
Save