qml 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +46 -0
- data/.rspec +2 -0
- data/.travis.yml +15 -0
- data/.yardopts +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +351 -0
- data/Rakefile +6 -0
- data/examples/assets/fonts/fontawesome-webfont.ttf +0 -0
- data/examples/fizzbuzz/fizzbuzz.rb +43 -0
- data/examples/fizzbuzz/main.qml +38 -0
- data/examples/imageprovider/imageprovider.rb +57 -0
- data/examples/imageprovider/main.qml +51 -0
- data/examples/todo/main.qml +70 -0
- data/examples/todo/todo.rb +36 -0
- data/examples/twitter/main.qml +36 -0
- data/examples/twitter/twitter.rb +55 -0
- data/ext/qml/accessclass.cpp +71 -0
- data/ext/qml/accessclass.h +19 -0
- data/ext/qml/accessobject.cpp +30 -0
- data/ext/qml/accessobject.h +22 -0
- data/ext/qml/application.cpp +54 -0
- data/ext/qml/application.h +17 -0
- data/ext/qml/common.h +18 -0
- data/ext/qml/ext_accesssupport.cpp +77 -0
- data/ext/qml/ext_accesssupport.h +42 -0
- data/ext/qml/ext_gcmarker.cpp +39 -0
- data/ext/qml/ext_gcmarker.h +27 -0
- data/ext/qml/ext_kernel.cpp +62 -0
- data/ext/qml/ext_kernel.h +11 -0
- data/ext/qml/ext_metaobject.cpp +410 -0
- data/ext/qml/ext_metaobject.h +62 -0
- data/ext/qml/ext_pluginloader.cpp +55 -0
- data/ext/qml/ext_pluginloader.h +32 -0
- data/ext/qml/ext_pointer.cpp +134 -0
- data/ext/qml/ext_pointer.h +43 -0
- data/ext/qml/ext_testutil.cpp +42 -0
- data/ext/qml/ext_testutil.h +11 -0
- data/ext/qml/extconf.rb +84 -0
- data/ext/qml/foreignclass.cpp +72 -0
- data/ext/qml/foreignclass.h +88 -0
- data/ext/qml/foreignmetaobject.cpp +345 -0
- data/ext/qml/foreignmetaobject.h +46 -0
- data/ext/qml/foreignobject.cpp +22 -0
- data/ext/qml/foreignobject.h +21 -0
- data/ext/qml/functioninfo.h +16 -0
- data/ext/qml/init.cpp +69 -0
- data/ext/qml/listmodel.cpp +112 -0
- data/ext/qml/listmodel.h +43 -0
- data/ext/qml/markable.h +12 -0
- data/ext/qml/objectdata.cpp +26 -0
- data/ext/qml/objectdata.h +20 -0
- data/ext/qml/objectgc.cpp +69 -0
- data/ext/qml/objectgc.h +28 -0
- data/ext/qml/plugins/core/applicationextension.cpp +34 -0
- data/ext/qml/plugins/core/applicationextension.h +28 -0
- data/ext/qml/plugins/core/componentextension.cpp +41 -0
- data/ext/qml/plugins/core/componentextension.h +28 -0
- data/ext/qml/plugins/core/contextextension.cpp +39 -0
- data/ext/qml/plugins/core/contextextension.h +29 -0
- data/ext/qml/plugins/core/core.pro +29 -0
- data/ext/qml/plugins/core/coreplugin.cpp +87 -0
- data/ext/qml/plugins/core/coreplugin.h +49 -0
- data/ext/qml/plugins/core/engineextension.cpp +27 -0
- data/ext/qml/plugins/core/engineextension.h +28 -0
- data/ext/qml/plugins/core/imageprovider.cpp +38 -0
- data/ext/qml/plugins/core/imageprovider.h +18 -0
- data/ext/qml/plugins/core/imagerequestpromise.cpp +19 -0
- data/ext/qml/plugins/core/imagerequestpromise.h +21 -0
- data/ext/qml/plugins/core/qmlexception.cpp +11 -0
- data/ext/qml/plugins/core/qmlexception.h +17 -0
- data/ext/qml/plugins/testutil/objectlifechecker.cpp +17 -0
- data/ext/qml/plugins/testutil/objectlifechecker.h +24 -0
- data/ext/qml/plugins/testutil/ownershiptest.cpp +26 -0
- data/ext/qml/plugins/testutil/ownershiptest.h +30 -0
- data/ext/qml/plugins/testutil/testobject.cpp +6 -0
- data/ext/qml/plugins/testutil/testobject.h +108 -0
- data/ext/qml/plugins/testutil/testobjectsubclass.cpp +10 -0
- data/ext/qml/plugins/testutil/testobjectsubclass.h +19 -0
- data/ext/qml/plugins/testutil/testutil.pro +20 -0
- data/ext/qml/plugins/testutil/testutilplugin.cpp +47 -0
- data/ext/qml/plugins/testutil/testutilplugin.h +32 -0
- data/ext/qml/qmltyperegisterer.cpp +74 -0
- data/ext/qml/qmltyperegisterer.h +30 -0
- data/ext/qml/rubyclass.cpp +94 -0
- data/ext/qml/rubyclass.h +234 -0
- data/ext/qml/rubyvalue.cpp +690 -0
- data/ext/qml/rubyvalue.h +256 -0
- data/ext/qml/signalforwarder.cpp +66 -0
- data/ext/qml/signalforwarder.h +29 -0
- data/ext/qml/util.cpp +120 -0
- data/ext/qml/util.h +101 -0
- data/ext/qml/valuereference.cpp +50 -0
- data/ext/qml/valuereference.h +22 -0
- data/ext/qml/weakvaluereference.cpp +27 -0
- data/ext/qml/weakvaluereference.h +19 -0
- data/lib/qml.rb +41 -0
- data/lib/qml/access.rb +137 -0
- data/lib/qml/application.rb +139 -0
- data/lib/qml/class_builder.rb +126 -0
- data/lib/qml/component.rb +53 -0
- data/lib/qml/context.rb +71 -0
- data/lib/qml/data.rb +2 -0
- data/lib/qml/data/array_model.rb +103 -0
- data/lib/qml/data/error.rb +5 -0
- data/lib/qml/data/list_model.rb +146 -0
- data/lib/qml/dispatchable.rb +34 -0
- data/lib/qml/dispatcher.rb +61 -0
- data/lib/qml/engine.rb +54 -0
- data/lib/qml/error_converter.rb +15 -0
- data/lib/qml/errors.rb +26 -0
- data/lib/qml/geometry.rb +3 -0
- data/lib/qml/geometry/point.rb +5 -0
- data/lib/qml/geometry/rectangle.rb +5 -0
- data/lib/qml/geometry/size.rb +5 -0
- data/lib/qml/image_provider.rb +87 -0
- data/lib/qml/meta_object.rb +20 -0
- data/lib/qml/models.rb +1 -0
- data/lib/qml/name_helper.rb +12 -0
- data/lib/qml/platform.rb +15 -0
- data/lib/qml/plugin_loader.rb +46 -0
- data/lib/qml/plugins.rb +26 -0
- data/lib/qml/qml.rb +1 -0
- data/lib/qml/qt.rb +6 -0
- data/lib/qml/qt_classes.rb +9 -0
- data/lib/qml/qt_object_base.rb +108 -0
- data/lib/qml/reactive.rb +8 -0
- data/lib/qml/reactive/bindable.rb +79 -0
- data/lib/qml/reactive/chained_signal.rb +25 -0
- data/lib/qml/reactive/error.rb +5 -0
- data/lib/qml/reactive/object.rb +278 -0
- data/lib/qml/reactive/property.rb +19 -0
- data/lib/qml/reactive/signal.rb +116 -0
- data/lib/qml/reactive/signal_spy.rb +27 -0
- data/lib/qml/reactive/signals/map_signal.rb +21 -0
- data/lib/qml/reactive/signals/merge_signal.rb +21 -0
- data/lib/qml/reactive/signals/select_signal.rb +21 -0
- data/lib/qml/reactive/simple_property.rb +17 -0
- data/lib/qml/reactive/unbound_property.rb +42 -0
- data/lib/qml/reactive/unbound_signal.rb +51 -0
- data/lib/qml/root_path.rb +3 -0
- data/lib/qml/test_util.rb +1 -0
- data/lib/qml/test_util/object_life_checker.rb +17 -0
- data/lib/qml/version.rb +3 -0
- data/lib/qml/wrappable.rb +9 -0
- data/qml.gemspec +28 -0
- data/spec/assets/testobj.qml +5 -0
- data/spec/qml/.access_spec.rb.swp +0 -0
- data/spec/qml/access_spec.rb +162 -0
- data/spec/qml/application_spec.rb +43 -0
- data/spec/qml/component_spec.rb +44 -0
- data/spec/qml/context_spec.rb +43 -0
- data/spec/qml/conversion_spec.rb +59 -0
- data/spec/qml/data/array_model_spec.rb +215 -0
- data/spec/qml/dispatchable_spec.rb +26 -0
- data/spec/qml/dispatcher_spec.rb +48 -0
- data/spec/qml/geometry/point_spec.rb +4 -0
- data/spec/qml/geometry/rectangle_spec.rb +4 -0
- data/spec/qml/geometry/size_spec.rb +4 -0
- data/spec/qml/plugin_loader_spec.rb +33 -0
- data/spec/qml/qt_object_base_spec.rb +119 -0
- data/spec/qml/reactive/object_spec.rb +273 -0
- data/spec/qml/reactive/property_spec.rb +70 -0
- data/spec/qml/reactive/signal_spec.rb +191 -0
- data/spec/qml/reactive/signal_spy_spec.rb +26 -0
- data/spec/qml/test_object_spec.rb +186 -0
- data/spec/qml_spec.rb +7 -0
- data/spec/spec_helper.rb +5 -0
- metadata +321 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include "foreignclass.h"
|
|
3
|
+
#include "rubyvalue.h"
|
|
4
|
+
|
|
5
|
+
namespace RubyQml {
|
|
6
|
+
|
|
7
|
+
class AccessWrapper;
|
|
8
|
+
|
|
9
|
+
class AccessClass : public ForeignClass
|
|
10
|
+
{
|
|
11
|
+
public:
|
|
12
|
+
AccessClass(RubyValue className, RubyValue methodInfos, RubyValue signalInfos, RubyValue propertyInfos);
|
|
13
|
+
|
|
14
|
+
QVariant callMethod(ForeignObject *obj, size_t id, const QVariantList &args) override;
|
|
15
|
+
void setProperty(ForeignObject *obj, size_t id, const QVariant &value) override;
|
|
16
|
+
QVariant getProperty(ForeignObject *obj, size_t id) override;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#include "accessobject.h"
|
|
2
|
+
#include "util.h"
|
|
3
|
+
#include "rubyclass.h"
|
|
4
|
+
#include <QSet>
|
|
5
|
+
|
|
6
|
+
namespace RubyQml {
|
|
7
|
+
|
|
8
|
+
AccessWrapper::AccessWrapper(const SP<ForeignMetaObject> &metaobj, RubyValue value) :
|
|
9
|
+
ForeignObject(metaobj),
|
|
10
|
+
mWrapped(value)
|
|
11
|
+
{
|
|
12
|
+
if (!value.isKindOf(RubyModule::fromPath("QML::Access"))) {
|
|
13
|
+
std::logic_error("wrapping non QML::Access object");
|
|
14
|
+
}
|
|
15
|
+
value.send("access_wrappers").send("push", RubyValue::fromQObject(this, false));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
AccessWrapper::~AccessWrapper()
|
|
19
|
+
{
|
|
20
|
+
if (mWrapped.hasValue()) {
|
|
21
|
+
mWrapped.value().send("access_wrappers").send("delete", RubyValue::fromQObject(this, false));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
void AccessWrapper::gc_mark()
|
|
26
|
+
{
|
|
27
|
+
rb_gc_mark(mWrapped.value());
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include "weakvaluereference.h"
|
|
3
|
+
#include "foreignobject.h"
|
|
4
|
+
#include "markable.h"
|
|
5
|
+
|
|
6
|
+
namespace RubyQml {
|
|
7
|
+
|
|
8
|
+
class AccessWrapper : public ForeignObject, public Markable
|
|
9
|
+
{
|
|
10
|
+
public:
|
|
11
|
+
AccessWrapper(const SP<ForeignMetaObject> &metaobj, RubyValue wrappedValue);
|
|
12
|
+
~AccessWrapper();
|
|
13
|
+
|
|
14
|
+
RubyValue wrappedValue() { return mWrapped.value(); }
|
|
15
|
+
void gc_mark() override;
|
|
16
|
+
|
|
17
|
+
private:
|
|
18
|
+
WeakValueReference mWrapped;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
} // namespace RubyQml
|
|
22
|
+
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#include "application.h"
|
|
2
|
+
#include "util.h"
|
|
3
|
+
|
|
4
|
+
namespace RubyQml {
|
|
5
|
+
namespace Application {
|
|
6
|
+
|
|
7
|
+
namespace {
|
|
8
|
+
|
|
9
|
+
int argc;
|
|
10
|
+
QList<QByteArray> argData;
|
|
11
|
+
char **argv;
|
|
12
|
+
|
|
13
|
+
QApplication *application_;
|
|
14
|
+
QQmlEngine *engine_;
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
void failIfUninitialized()
|
|
19
|
+
{
|
|
20
|
+
if (!initialized()) {
|
|
21
|
+
fail("QML::UninitializedError", "ruby-qml not yet initialized");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
QApplication *application()
|
|
26
|
+
{
|
|
27
|
+
failIfUninitialized();
|
|
28
|
+
return application_;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
QQmlEngine *engine()
|
|
32
|
+
{
|
|
33
|
+
failIfUninitialized();
|
|
34
|
+
return engine_;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
bool initialized()
|
|
38
|
+
{
|
|
39
|
+
return application_;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
void init(const QList<QByteArray> &args)
|
|
43
|
+
{
|
|
44
|
+
argc = args.size();
|
|
45
|
+
argData = args;
|
|
46
|
+
argv = new char*[argc];
|
|
47
|
+
std::transform(argData.begin(), argData.end(), argv, [](QByteArray &ba) { return ba.data(); });
|
|
48
|
+
|
|
49
|
+
application_ = new QApplication(argc, argv);
|
|
50
|
+
engine_ = new QQmlEngine();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
}
|
|
54
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <QList>
|
|
4
|
+
#include <QApplication>
|
|
5
|
+
#include <QQmlEngine>
|
|
6
|
+
|
|
7
|
+
namespace RubyQml {
|
|
8
|
+
namespace Application {
|
|
9
|
+
|
|
10
|
+
QApplication *application();
|
|
11
|
+
QQmlEngine *engine();
|
|
12
|
+
bool initialized();
|
|
13
|
+
|
|
14
|
+
void init(const QList<QByteArray> &args);
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
} // namespace RubyQml
|
data/ext/qml/common.h
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <memory>
|
|
3
|
+
|
|
4
|
+
namespace RubyQml {
|
|
5
|
+
|
|
6
|
+
template <typename T>
|
|
7
|
+
using SP = std::shared_ptr<T>;
|
|
8
|
+
|
|
9
|
+
template <typename T>
|
|
10
|
+
using WP = std::weak_ptr<T>;
|
|
11
|
+
|
|
12
|
+
template <typename T, typename ... Args>
|
|
13
|
+
inline SP<T> makeSP(Args && ... args)
|
|
14
|
+
{
|
|
15
|
+
return std::make_shared<T>(std::forward<Args>(args)...);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#include "ext_accesssupport.h"
|
|
2
|
+
#include "ext_pointer.h"
|
|
3
|
+
#include "rubyclass.h"
|
|
4
|
+
#include "accessclass.h"
|
|
5
|
+
#include "accessobject.h"
|
|
6
|
+
#include "foreignmetaobject.h"
|
|
7
|
+
#include "qmltyperegisterer.h"
|
|
8
|
+
|
|
9
|
+
namespace RubyQml {
|
|
10
|
+
namespace Ext {
|
|
11
|
+
|
|
12
|
+
AccessWrapperFactory::AccessWrapperFactory(RubyValue self) :
|
|
13
|
+
self(self)
|
|
14
|
+
{
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
AccessWrapperFactory::~AccessWrapperFactory()
|
|
18
|
+
{
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
RubyValue AccessWrapperFactory::ext_initialize(RubyValue rubyClass, RubyValue className, RubyValue methodInfos, RubyValue signalInfos, RubyValue propertyInfos)
|
|
22
|
+
{
|
|
23
|
+
mRubyClass = rubyClass;
|
|
24
|
+
mAccessClass = makeSP<AccessClass>(className, methodInfos, signalInfos, propertyInfos);
|
|
25
|
+
mMetaObject = makeSP<ForeignMetaObject>(mAccessClass);
|
|
26
|
+
return self;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
RubyValue AccessWrapperFactory::ext_emitSignal(RubyValue obj, RubyValue name, RubyValue args)
|
|
30
|
+
{
|
|
31
|
+
auto accessObj = wrapperRubyClass<Pointer>().unwrap(obj.send("access_object"))->fetchQObject();
|
|
32
|
+
auto nameId = name.toID();
|
|
33
|
+
auto argVariants = args.to<QVariantList>();
|
|
34
|
+
withoutGvl([&] {
|
|
35
|
+
mMetaObject->emitSignal(dynamic_cast<ForeignObject *>(accessObj), nameId, argVariants);
|
|
36
|
+
});
|
|
37
|
+
return Qnil;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
RubyValue AccessWrapperFactory::ext_registerToQml(RubyValue path, RubyValue majorVersion, RubyValue minorVersion, RubyValue name)
|
|
41
|
+
{
|
|
42
|
+
using namespace std::placeholders;
|
|
43
|
+
if (!mTypeRegisterer) {
|
|
44
|
+
mTypeRegisterer = makeSP<QmlTypeRegisterer>(mMetaObject, std::bind(&AccessWrapperFactory::newInstanceInto, this, _1));
|
|
45
|
+
mTypeRegisterer->registerType(path.to<QByteArray>(), majorVersion.to<int>(), minorVersion.to<int>(), name.to<QByteArray>());
|
|
46
|
+
}
|
|
47
|
+
return self;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
RubyValue AccessWrapperFactory::ext_create(RubyValue access)
|
|
51
|
+
{
|
|
52
|
+
return RubyValue::fromQObject(create(access), false);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
AccessWrapper *AccessWrapperFactory::create(RubyValue access)
|
|
56
|
+
{
|
|
57
|
+
return new AccessWrapper(mMetaObject, access);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
void AccessWrapperFactory::newInstanceInto(void *where)
|
|
61
|
+
{
|
|
62
|
+
withGvl([&] {
|
|
63
|
+
new(where) AccessWrapper(mMetaObject, mRubyClass.send("new"));
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
void AccessWrapperFactory::defineClass()
|
|
68
|
+
{
|
|
69
|
+
WrapperRubyClass<AccessWrapperFactory> klass(RubyModule::fromPath("QML"), "AccessWrapperFactory");
|
|
70
|
+
klass.defineMethod(MethodAccess::Protected, "initialize", RUBYQML_MEMBER_FUNCTION_INFO(&AccessWrapperFactory::ext_initialize));
|
|
71
|
+
klass.defineMethod("emit_signal", RUBYQML_MEMBER_FUNCTION_INFO(&AccessWrapperFactory::ext_emitSignal));
|
|
72
|
+
klass.defineMethod("register_to_qml", RUBYQML_MEMBER_FUNCTION_INFO(&AccessWrapperFactory::ext_registerToQml));
|
|
73
|
+
klass.defineMethod("create", RUBYQML_MEMBER_FUNCTION_INFO(&AccessWrapperFactory::ext_create));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
} // namespace Ext
|
|
77
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include "common.h"
|
|
3
|
+
#include "rubyvalue.h"
|
|
4
|
+
|
|
5
|
+
namespace RubyQml {
|
|
6
|
+
|
|
7
|
+
class AccessClass;
|
|
8
|
+
class ForeignMetaObject;
|
|
9
|
+
class QmlTypeRegisterer;
|
|
10
|
+
class AccessWrapper;
|
|
11
|
+
|
|
12
|
+
namespace Ext {
|
|
13
|
+
|
|
14
|
+
class AccessWrapperFactory
|
|
15
|
+
{
|
|
16
|
+
public:
|
|
17
|
+
AccessWrapperFactory(RubyValue self);
|
|
18
|
+
~AccessWrapperFactory();
|
|
19
|
+
|
|
20
|
+
RubyValue ext_initialize(RubyValue rubyClass, RubyValue className, RubyValue methodInfos, RubyValue signalInfos, RubyValue propertyInfos);
|
|
21
|
+
RubyValue ext_emitSignal(RubyValue obj, RubyValue name, RubyValue args);
|
|
22
|
+
RubyValue ext_registerToQml(RubyValue path, RubyValue majorVersion, RubyValue minorVersion, RubyValue name);
|
|
23
|
+
RubyValue ext_create(RubyValue access);
|
|
24
|
+
|
|
25
|
+
AccessWrapper *create(RubyValue access);
|
|
26
|
+
|
|
27
|
+
void gc_mark() {}
|
|
28
|
+
static void defineClass();
|
|
29
|
+
|
|
30
|
+
private:
|
|
31
|
+
|
|
32
|
+
void newInstanceInto(void *where);
|
|
33
|
+
|
|
34
|
+
const RubyValue self;
|
|
35
|
+
RubyValue mRubyClass;
|
|
36
|
+
SP<AccessClass> mAccessClass;
|
|
37
|
+
SP<ForeignMetaObject> mMetaObject;
|
|
38
|
+
SP<QmlTypeRegisterer> mTypeRegisterer;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
} // namespace Ext
|
|
42
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#include "ext_gcmarker.h"
|
|
2
|
+
#include "rubyclass.h"
|
|
3
|
+
#include <QtCore/QSet>
|
|
4
|
+
|
|
5
|
+
namespace RubyQml {
|
|
6
|
+
namespace Ext {
|
|
7
|
+
|
|
8
|
+
GCMarker::GCMarker(RubyValue self)
|
|
9
|
+
{
|
|
10
|
+
Q_UNUSED(self)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
RubyValue GCMarker::fromMarkFunction(const std::function<void ()> &func)
|
|
14
|
+
{
|
|
15
|
+
auto klass = wrapperRubyClass<GCMarker>();
|
|
16
|
+
auto marker = klass.newInstance();
|
|
17
|
+
klass.unwrap(marker)->setMarkFunction(func);
|
|
18
|
+
return marker;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
void GCMarker::setMarkFunction(const std::function<void ()> &func)
|
|
22
|
+
{
|
|
23
|
+
mMarkFunc = func;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
void GCMarker::gc_mark()
|
|
27
|
+
{
|
|
28
|
+
if (mMarkFunc)
|
|
29
|
+
mMarkFunc();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
void GCMarker::defineClass()
|
|
33
|
+
{
|
|
34
|
+
WrapperRubyClass<GCMarker> klass(RubyModule::fromPath("QML"), "GCProtection");
|
|
35
|
+
Q_UNUSED(klass);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
} // namespace Ext
|
|
39
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "rubyvalue.h"
|
|
4
|
+
#include <functional>
|
|
5
|
+
|
|
6
|
+
namespace RubyQml {
|
|
7
|
+
|
|
8
|
+
namespace Ext {
|
|
9
|
+
|
|
10
|
+
class GCMarker
|
|
11
|
+
{
|
|
12
|
+
public:
|
|
13
|
+
GCMarker(RubyValue self);
|
|
14
|
+
static RubyValue fromMarkFunction(const std::function<void ()> &func);
|
|
15
|
+
|
|
16
|
+
void setMarkFunction(const std::function<void()> &func);
|
|
17
|
+
void gc_mark();
|
|
18
|
+
|
|
19
|
+
static void defineClass();
|
|
20
|
+
|
|
21
|
+
private:
|
|
22
|
+
std::function<void ()> mMarkFunc;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
} // namespace Ext
|
|
26
|
+
|
|
27
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#include "ext_kernel.h"
|
|
2
|
+
#include "application.h"
|
|
3
|
+
#include "rubyvalue.h"
|
|
4
|
+
#include "rubyclass.h"
|
|
5
|
+
|
|
6
|
+
namespace RubyQml {
|
|
7
|
+
namespace Ext {
|
|
8
|
+
namespace Kernel {
|
|
9
|
+
|
|
10
|
+
namespace {
|
|
11
|
+
|
|
12
|
+
RubyValue application(RubyValue self)
|
|
13
|
+
{
|
|
14
|
+
Q_UNUSED(self);
|
|
15
|
+
return RubyValue::from(Application::application());
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
RubyValue engine(RubyValue self)
|
|
19
|
+
{
|
|
20
|
+
Q_UNUSED(self);
|
|
21
|
+
return RubyValue::from(Application::engine());
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
RubyValue applicationMetaObject()
|
|
25
|
+
{
|
|
26
|
+
return RubyValue::from(&QApplication::staticMetaObject);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
RubyValue engineMetaObject()
|
|
30
|
+
{
|
|
31
|
+
return RubyValue::from(&QQmlEngine::staticMetaObject);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
RubyValue init(RubyValue self, RubyValue argv)
|
|
35
|
+
{
|
|
36
|
+
Q_UNUSED(self);
|
|
37
|
+
Application::init(argv.to<QList<QByteArray>>());
|
|
38
|
+
return Qnil;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
RubyValue initialized(RubyValue self)
|
|
42
|
+
{
|
|
43
|
+
Q_UNUSED(self);
|
|
44
|
+
return RubyValue::from(Application::initialized());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
void defineModule()
|
|
50
|
+
{
|
|
51
|
+
RubyModule kernel(RubyModule::fromPath("QML"), "Kernel");
|
|
52
|
+
kernel.defineModuleFunction("application", RUBYQML_FUNCTION_INFO(&application));
|
|
53
|
+
kernel.defineModuleFunction("engine", RUBYQML_FUNCTION_INFO(&engine));
|
|
54
|
+
kernel.defineModuleFunction("application_meta_object", RUBYQML_FUNCTION_INFO(&applicationMetaObject));
|
|
55
|
+
kernel.defineModuleFunction("engine_meta_object", RUBYQML_FUNCTION_INFO(&engineMetaObject));
|
|
56
|
+
kernel.defineModuleFunction("init", RUBYQML_FUNCTION_INFO(&init));
|
|
57
|
+
kernel.defineModuleFunction("initialized?", RUBYQML_FUNCTION_INFO(&initialized));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
} // namespace Kernel
|
|
61
|
+
} // namespace Ext
|
|
62
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
#include "ext_metaobject.h"
|
|
2
|
+
#include "util.h"
|
|
3
|
+
#include "ext_pointer.h"
|
|
4
|
+
#include "rubyclass.h"
|
|
5
|
+
#include "signalforwarder.h"
|
|
6
|
+
#include <QtCore/QMetaObject>
|
|
7
|
+
#include <QtCore/QMetaMethod>
|
|
8
|
+
#include <QtCore/QMetaProperty>
|
|
9
|
+
#include <QtCore/QMetaEnum>
|
|
10
|
+
#include <QtCore/QVariant>
|
|
11
|
+
#include <array>
|
|
12
|
+
#include <QtCore/QDebug>
|
|
13
|
+
#include <QtQml/QQmlEngine>
|
|
14
|
+
|
|
15
|
+
namespace RubyQml {
|
|
16
|
+
namespace Ext {
|
|
17
|
+
|
|
18
|
+
namespace {
|
|
19
|
+
|
|
20
|
+
RubyValue idListToArray(const QList<ID> &xs)
|
|
21
|
+
{
|
|
22
|
+
return protect([&] {
|
|
23
|
+
auto ary = rb_ary_new();
|
|
24
|
+
for (ID id : xs) {
|
|
25
|
+
rb_ary_push(ary, ID2SYM(id));
|
|
26
|
+
}
|
|
27
|
+
return ary;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
MetaObject::MetaObject(RubyValue self) :
|
|
34
|
+
self(self)
|
|
35
|
+
{
|
|
36
|
+
setMetaObject(&QObject::staticMetaObject);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
RubyValue MetaObject::className() const
|
|
40
|
+
{
|
|
41
|
+
return rb_str_new_cstr(mMetaObject->className());
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
RubyValue MetaObject::methodNames() const
|
|
45
|
+
{
|
|
46
|
+
return idListToArray(mMethodHash.keys());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
RubyValue MetaObject::isPublic(RubyValue name) const
|
|
50
|
+
{
|
|
51
|
+
auto methods = findMethods(name);
|
|
52
|
+
return RubyValue::from(mMetaObject->method(methods.first()).access() == QMetaMethod::Public);
|
|
53
|
+
}
|
|
54
|
+
RubyValue MetaObject::isProtected(RubyValue name) const
|
|
55
|
+
{
|
|
56
|
+
auto methods = findMethods(name);
|
|
57
|
+
return RubyValue::from(mMetaObject->method(methods.first()).access() == QMetaMethod::Protected);
|
|
58
|
+
}
|
|
59
|
+
RubyValue MetaObject::isPrivate(RubyValue name) const
|
|
60
|
+
{
|
|
61
|
+
auto methods = findMethods(name);
|
|
62
|
+
return RubyValue::from(mMetaObject->method(methods.first()).access() == QMetaMethod::Private);
|
|
63
|
+
}
|
|
64
|
+
RubyValue MetaObject::isSignal(RubyValue name) const
|
|
65
|
+
{
|
|
66
|
+
auto methods = findMethods(name);
|
|
67
|
+
return RubyValue::from(mMetaObject->method(methods.first()).methodType() == QMetaMethod::Signal);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
class MethodInvoker
|
|
71
|
+
{
|
|
72
|
+
public:
|
|
73
|
+
MethodInvoker(RubyValue args, const QMetaMethod &method) :
|
|
74
|
+
mArgs(args), mMethod(method) {}
|
|
75
|
+
|
|
76
|
+
bool isArgsCompatible() const
|
|
77
|
+
{
|
|
78
|
+
int count = RARRAY_LEN(VALUE(mArgs));
|
|
79
|
+
if (mMethod.parameterCount() != count) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
for (int i = 0; i < count; ++i) {
|
|
83
|
+
auto metaType = mMethod.parameterType(i);
|
|
84
|
+
RubyValue arg = RARRAY_AREF(VALUE(mArgs), i);
|
|
85
|
+
if (!arg.isConvertibleTo(metaType)) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
RubyValue invoke(QObject *obj)
|
|
93
|
+
{
|
|
94
|
+
std::array<QVariant, 10> argVariants;
|
|
95
|
+
std::array<QGenericArgument, 10> args;
|
|
96
|
+
for (int i = 0; i < mMethod.parameterCount(); ++i) {
|
|
97
|
+
auto metaType = mMethod.parameterType(i);
|
|
98
|
+
argVariants[i] = RubyValue(RARRAY_AREF(VALUE(mArgs), i)).toVariant(metaType);
|
|
99
|
+
args[i] = QGenericArgument(QMetaType::typeName(metaType), argVariants[i].data());
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
int returnType = mMethod.returnType();
|
|
103
|
+
if (returnType == QMetaType::UnknownType) {
|
|
104
|
+
fail("QML::MethodError", "unknown return metatype");
|
|
105
|
+
}
|
|
106
|
+
bool voidReturning = (returnType == QMetaType::Void);
|
|
107
|
+
QVariant returnValue;
|
|
108
|
+
if (!voidReturning) {
|
|
109
|
+
returnValue = QVariant(returnType, QMetaType::create(returnType));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
bool result;
|
|
113
|
+
withoutGvl([&] {
|
|
114
|
+
result = mMethod.invoke(
|
|
115
|
+
obj,
|
|
116
|
+
Qt::DirectConnection,
|
|
117
|
+
QGenericReturnArgument(QMetaType::typeName(returnType), returnValue.data()),
|
|
118
|
+
args[0],args[1],args[2],args[3],args[4],
|
|
119
|
+
args[5],args[6],args[7],args[8],args[9]);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
if (!result) {
|
|
123
|
+
QString error;
|
|
124
|
+
QDebug(&error) << "failed to call method" << mMethod.methodSignature();
|
|
125
|
+
fail("QML::MethodError", error);
|
|
126
|
+
}
|
|
127
|
+
if (voidReturning) {
|
|
128
|
+
return Qnil;
|
|
129
|
+
} else {
|
|
130
|
+
auto ret = RubyValue::from(returnValue);
|
|
131
|
+
static auto objectBaseClass = RubyClass::fromPath("QML::QtObjectBase");
|
|
132
|
+
if (ret.isKindOf(objectBaseClass)) {
|
|
133
|
+
auto pointer = wrapperRubyClass<Pointer>().unwrap(ret.send("pointer"));
|
|
134
|
+
pointer->preferManaged(true);
|
|
135
|
+
}
|
|
136
|
+
return ret;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
private:
|
|
140
|
+
RubyValue mArgs;
|
|
141
|
+
QMetaMethod mMethod;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
RubyValue MetaObject::invokeMethod(RubyValue object, RubyValue methodName, RubyValue args) const
|
|
145
|
+
{
|
|
146
|
+
checkThread();
|
|
147
|
+
|
|
148
|
+
auto methodIndexes = findMethods(methodName);
|
|
149
|
+
|
|
150
|
+
protect([&] {
|
|
151
|
+
args = rb_check_array_type(args);
|
|
152
|
+
});
|
|
153
|
+
auto obj = wrapperRubyClass<Pointer>().unwrap(object)->fetchQObject();
|
|
154
|
+
for (int i : methodIndexes) {
|
|
155
|
+
MethodInvoker invoker(args, mMetaObject->method(i));
|
|
156
|
+
if (invoker.isArgsCompatible()) {
|
|
157
|
+
return invoker.invoke(obj);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
protect([&] {
|
|
161
|
+
auto to_class = rb_funcall(ID2SYM(rb_intern("class")), rb_intern("to_proc"), 0);
|
|
162
|
+
auto classes = rb_funcall_with_block(args, rb_intern("map"), 0, nullptr, to_class);
|
|
163
|
+
auto classes_str = rb_funcall(classes, rb_intern("to_s"), 0);
|
|
164
|
+
|
|
165
|
+
rb_raise(rb_path2class("QML::MethodError"),
|
|
166
|
+
"method mismatch (%s with params %s in %s)",
|
|
167
|
+
mMetaObject->method(methodIndexes.first()).name().data(),
|
|
168
|
+
StringValueCStr(classes_str),
|
|
169
|
+
mMetaObject->className());
|
|
170
|
+
});
|
|
171
|
+
return Qnil;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
RubyValue MetaObject::connectSignal(RubyValue object, RubyValue signalName, RubyValue proc) const
|
|
175
|
+
{
|
|
176
|
+
auto id = signalName.toID();
|
|
177
|
+
auto obj = wrapperRubyClass<Pointer>().unwrap(object)->fetchQObject();
|
|
178
|
+
|
|
179
|
+
proc = proc.send("to_proc");
|
|
180
|
+
|
|
181
|
+
auto methodIndexes = mMethodHash.values(id);
|
|
182
|
+
std::reverse(methodIndexes.begin(), methodIndexes.end());
|
|
183
|
+
|
|
184
|
+
for (int i : methodIndexes) {
|
|
185
|
+
auto method = mMetaObject->method(i);
|
|
186
|
+
if (method.methodType() != QMetaMethod::Signal) {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
new SignalForwarder(obj, method, proc);
|
|
190
|
+
return Qnil;
|
|
191
|
+
}
|
|
192
|
+
protect([&] {
|
|
193
|
+
rb_raise(rb_path2class("QML::MethodError"),
|
|
194
|
+
"signal not found (%s in %s)",
|
|
195
|
+
rb_id2name(id), mMetaObject->className());
|
|
196
|
+
});
|
|
197
|
+
return Qnil;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
RubyValue MetaObject::propertyNames() const
|
|
201
|
+
{
|
|
202
|
+
return idListToArray(mPropertyHash.keys());
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
RubyValue MetaObject::getProperty(RubyValue object, RubyValue name) const
|
|
206
|
+
{
|
|
207
|
+
checkThread();
|
|
208
|
+
|
|
209
|
+
auto metaProperty = mMetaObject->property(findProperty(name));
|
|
210
|
+
|
|
211
|
+
auto qobj = wrapperRubyClass<Pointer>().unwrap(object)->fetchQObject();
|
|
212
|
+
QVariant result;
|
|
213
|
+
withoutGvl([&] {
|
|
214
|
+
result = metaProperty.read(qobj);
|
|
215
|
+
});
|
|
216
|
+
return RubyValue::from(result);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
RubyValue MetaObject::setProperty(RubyValue object, RubyValue name, RubyValue newValue) const
|
|
220
|
+
{
|
|
221
|
+
checkThread();
|
|
222
|
+
|
|
223
|
+
auto metaProperty = mMetaObject->property(findProperty(name));
|
|
224
|
+
if (!newValue.isConvertibleTo(metaProperty.userType())) {
|
|
225
|
+
protect([&] {
|
|
226
|
+
rb_raise(rb_path2class("QML::PropertyError"),
|
|
227
|
+
"type mismatch (%s for %s)",
|
|
228
|
+
rb_obj_classname(newValue), metaProperty.typeName());
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
auto qobj = wrapperRubyClass<Pointer>().unwrap(object)->fetchQObject();
|
|
233
|
+
auto variant = newValue.to<QVariant>();
|
|
234
|
+
QVariant result;
|
|
235
|
+
withoutGvl([&] {
|
|
236
|
+
metaProperty.write(qobj, variant);
|
|
237
|
+
result = metaProperty.read(qobj);
|
|
238
|
+
});
|
|
239
|
+
return RubyValue::from(result);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
RubyValue MetaObject::notifySignal(RubyValue name) const
|
|
243
|
+
{
|
|
244
|
+
auto metaProperty = mMetaObject->property(findProperty(name));
|
|
245
|
+
auto signal = metaProperty.notifySignal();
|
|
246
|
+
if (signal.isValid()) {
|
|
247
|
+
return ID2SYM(rb_intern(metaProperty.notifySignal().name()));
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
return Qnil;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
void MetaObject::checkThread() const
|
|
255
|
+
{
|
|
256
|
+
if (rb_thread_current() != rb_thread_main()) {
|
|
257
|
+
fail("QML::InvalidThreadError", "Qt object accessed from non-main thread");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
QList<int> MetaObject::findMethods(RubyValue name) const
|
|
262
|
+
{
|
|
263
|
+
auto id = name.toID();
|
|
264
|
+
auto methodIndexes = mMethodHash.values(id);
|
|
265
|
+
if (methodIndexes.size() == 0) {
|
|
266
|
+
protect([&] {
|
|
267
|
+
rb_raise(rb_path2class("QML::MethodError"),
|
|
268
|
+
"method not found (%s in %s)",
|
|
269
|
+
rb_id2name(id),
|
|
270
|
+
mMetaObject->className());
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
return methodIndexes;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
int MetaObject::findProperty(RubyValue name) const
|
|
277
|
+
{
|
|
278
|
+
auto id = name.toID();
|
|
279
|
+
if (!mPropertyHash.contains(id)) {
|
|
280
|
+
protect([&] {
|
|
281
|
+
rb_raise(rb_path2class("QML::PropertyError"),
|
|
282
|
+
"property not found (%s in %s)",
|
|
283
|
+
rb_id2name(id), mMetaObject->className());
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
return mPropertyHash[id];
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
RubyValue MetaObject::enumerators() const
|
|
290
|
+
{
|
|
291
|
+
QHash<QByteArray, QHash<QByteArray, int>> enums;
|
|
292
|
+
|
|
293
|
+
for (int i = mMetaObject->enumeratorOffset(); i < mMetaObject->enumeratorCount(); ++i) {
|
|
294
|
+
auto metaEnum = mMetaObject->enumerator(i);
|
|
295
|
+
if (metaEnum.isFlag()) {
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
QHash<QByteArray, int> enumHash;
|
|
300
|
+
for (int j = 0; j < metaEnum.keyCount(); ++j) {
|
|
301
|
+
enumHash[metaEnum.key(j)] = metaEnum.value(j);
|
|
302
|
+
}
|
|
303
|
+
enums[metaEnum.name()] = enumHash;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return RubyValue::from(enums);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
RubyValue MetaObject::superClass() const
|
|
310
|
+
{
|
|
311
|
+
auto superclass = mMetaObject->superClass();
|
|
312
|
+
if (!superclass) {
|
|
313
|
+
return Qnil;
|
|
314
|
+
}
|
|
315
|
+
return fromMetaObject(superclass);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
RubyValue MetaObject::isEqual(RubyValue other) const
|
|
319
|
+
{
|
|
320
|
+
return RubyValue::from(mMetaObject == wrapperRubyClass<MetaObject>().unwrap(other)->mMetaObject);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
RubyValue MetaObject::hash() const
|
|
324
|
+
{
|
|
325
|
+
return RubyValue::from(reinterpret_cast<size_t>(mMetaObject)).send("hash");
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
void MetaObject::setMetaObject(const QMetaObject *metaObject)
|
|
329
|
+
{
|
|
330
|
+
int methodCount = metaObject->methodCount() - metaObject->methodOffset();
|
|
331
|
+
|
|
332
|
+
QMultiHash<ID, int> methodHash;
|
|
333
|
+
QHash<ID, int> propertyHash;
|
|
334
|
+
|
|
335
|
+
for (int i = 0; i < methodCount; ++i) {
|
|
336
|
+
|
|
337
|
+
auto index = i + metaObject->methodOffset();
|
|
338
|
+
auto method = metaObject->method(index);
|
|
339
|
+
|
|
340
|
+
if (method.methodType() == QMetaMethod::Constructor) {
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
methodHash.insert(rb_intern(method.name()), index);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
int propertyCount = metaObject->propertyCount() - metaObject->propertyOffset();
|
|
348
|
+
|
|
349
|
+
for (int i = 0; i < propertyCount; ++i) {
|
|
350
|
+
auto index = i + metaObject->propertyOffset();
|
|
351
|
+
auto property = metaObject->property(index);
|
|
352
|
+
propertyHash[rb_intern(property.name())] = index;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
int enumCount = metaObject->enumeratorCount() - metaObject->enumeratorOffset();
|
|
356
|
+
for (int i = 0; i < enumCount; ++i) {
|
|
357
|
+
auto index = i + metaObject->enumeratorOffset();
|
|
358
|
+
auto metaEnum = metaObject->enumerator(index);
|
|
359
|
+
auto typeName = QByteArray(metaObject->className()) + "::" + QByteArray(metaEnum.name());
|
|
360
|
+
auto metaType = QMetaType::type(typeName);
|
|
361
|
+
if (metaType != QMetaType::UnknownType) {
|
|
362
|
+
RubyValue::addEnumeratorMetaType(metaType);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
mMetaObject = metaObject;
|
|
367
|
+
mMethodHash = methodHash;
|
|
368
|
+
mPropertyHash = propertyHash;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
RubyValue MetaObject::fromMetaObject(const QMetaObject *metaObject)
|
|
372
|
+
{
|
|
373
|
+
auto klass = wrapperRubyClass<MetaObject>();
|
|
374
|
+
auto value = klass.newInstance();
|
|
375
|
+
klass.unwrap(value)->setMetaObject(metaObject);
|
|
376
|
+
return value;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
void MetaObject::defineClass()
|
|
380
|
+
{
|
|
381
|
+
WrapperRubyClass<MetaObject> klass(RubyModule::fromPath("QML"), "MetaObject");
|
|
382
|
+
|
|
383
|
+
klass.defineMethod("name", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::className));
|
|
384
|
+
|
|
385
|
+
klass.defineMethod("method_names", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::methodNames));
|
|
386
|
+
klass.defineMethod("public?", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::isPublic));
|
|
387
|
+
klass.defineMethod("protected?", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::isProtected));
|
|
388
|
+
klass.defineMethod("private?", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::isPrivate));
|
|
389
|
+
klass.defineMethod("signal?", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::isSignal));
|
|
390
|
+
|
|
391
|
+
klass.defineMethod("invoke_method", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::invokeMethod));
|
|
392
|
+
klass.defineMethod("connect_signal", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::connectSignal));
|
|
393
|
+
|
|
394
|
+
klass.defineMethod("property_names", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::propertyNames));
|
|
395
|
+
klass.defineMethod("get_property", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::getProperty));
|
|
396
|
+
klass.defineMethod("set_property", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::setProperty));
|
|
397
|
+
klass.defineMethod("notify_signal", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::notifySignal));
|
|
398
|
+
|
|
399
|
+
klass.defineMethod("enumerators", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::enumerators));
|
|
400
|
+
|
|
401
|
+
klass.defineMethod("super_class", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::superClass));
|
|
402
|
+
|
|
403
|
+
klass.defineMethod("==", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::isEqual));
|
|
404
|
+
klass.defineMethod("hash", RUBYQML_MEMBER_FUNCTION_INFO(&MetaObject::hash));
|
|
405
|
+
|
|
406
|
+
klass.aliasMethod("eql?", "==");
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
} // namespace Ext
|
|
410
|
+
} // namespace RubyQml
|