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

16
src/mvvmcore/qtmvvmcore_helpertypes.h

@ -52,19 +52,19 @@ inline QByteArray inject_iid() {
}
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>());
auto subFn = [fn](const QVariantList &params, int index, TArgs... tArgs) {
auto subFn = [fn](const QObjectList &params, int index, TArgs... tArgs) {
--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);
}
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)
return [fn](const QVariantList &params) {
return [fn](const QObjectList &params) {
return fn(params, params.size());
};
}
@ -76,8 +76,8 @@ 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* {
static inline Q_CONSTEXPR std::function<QObject*(QObjectList)> pack(const TFunctor &fn, QByteArrayList &injectables) {
auto subFn = [fn](const QObjectList &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...);
@ -87,7 +87,7 @@ struct fn_info<TRet(TClass::*)(TArgs...) const>
};
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);
}

81
src/mvvmcore/serviceregistry.cpp

@ -2,6 +2,8 @@
#include "serviceregistry_p.h"
#include <QtCore/QGlobalStatic>
#include <QtCore/QRegularExpression>
#include <QtCore/QMetaProperty>
using namespace QtMvvm;
@ -19,17 +21,88 @@ ServiceRegistry *ServiceRegistry::instance()
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 -------------
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,
const QMetaObject *metaObject);
void registerService(const QByteArray &iid,
const std::function<QObject*(const QVariantList&)> &fn,
const std::function<QObject*(const QObjectList &)> &fn,
QByteArrayList injectables);
private:
@ -65,7 +65,7 @@ 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* {
registerService(qobject_interface_iid<TInterface*>(), [service](const QObjectList &params) -> QObject* {
Q_UNUSED(params);
return service;
}, QByteArrayList());
@ -95,7 +95,7 @@ template<typename TService>
void ServiceRegistry::registerObject(TService *service)
{
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);
return service;
}, QByteArrayList());

42
src/mvvmcore/serviceregistry_p.h

@ -1,6 +1,8 @@
#ifndef QTMVVM_SERVICEREGISTRY_P_H
#define QTMVVM_SERVICEREGISTRY_P_H
#include <QtCore/QMutex>
#include "qtmvvmcore_global.h"
#include "serviceregistry.h"
@ -9,6 +11,46 @@ namespace QtMvvm {
class ServiceRegistryPrivate
{
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();
};

Loading…
Cancel
Save