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,72 @@
|
|
|
1
|
+
#include "foreignclass.h"
|
|
2
|
+
#include "foreignobject.h"
|
|
3
|
+
#include <QDebug>
|
|
4
|
+
|
|
5
|
+
namespace RubyQml {
|
|
6
|
+
|
|
7
|
+
ForeignClass::ForeignClass()
|
|
8
|
+
{
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
ForeignClass::~ForeignClass()
|
|
12
|
+
{
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
QList<ForeignClass::Method> ForeignClass::signalMethods() const
|
|
16
|
+
{
|
|
17
|
+
QList<Method> sigs;
|
|
18
|
+
std::copy_if(mMethods.begin(), mMethods.end(), std::back_inserter(sigs), [](const Method &m) {
|
|
19
|
+
return m.type == Method::Type::Signal;
|
|
20
|
+
});
|
|
21
|
+
return sigs;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
QList<ForeignClass::Method> ForeignClass::nonSignalMethods() const
|
|
25
|
+
{
|
|
26
|
+
QList<Method> sigs;
|
|
27
|
+
std::copy_if(mMethods.begin(), mMethods.end(), std::back_inserter(sigs), [](const Method &m) {
|
|
28
|
+
return m.type != Method::Type::Signal;
|
|
29
|
+
});
|
|
30
|
+
return sigs;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
QVariant ForeignClass::callMethod(ForeignObject *obj, size_t id, const QVariantList &args)
|
|
34
|
+
{
|
|
35
|
+
Q_UNUSED(obj);
|
|
36
|
+
Q_UNUSED(id);
|
|
37
|
+
Q_UNUSED(args);
|
|
38
|
+
return QVariant();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
void ForeignClass::setProperty(ForeignObject *obj, size_t id, const QVariant &value)
|
|
42
|
+
{
|
|
43
|
+
Q_UNUSED(obj);
|
|
44
|
+
Q_UNUSED(id);
|
|
45
|
+
Q_UNUSED(value);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
QVariant ForeignClass::getProperty(ForeignObject *obj, size_t id)
|
|
49
|
+
{
|
|
50
|
+
Q_UNUSED(obj);
|
|
51
|
+
Q_UNUSED(id);
|
|
52
|
+
return QVariant();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
void ForeignClass::addMethod(const QByteArray &name, std::size_t id, const QList<QByteArray> ¶ms, Method::Access access, Method::Type type)
|
|
56
|
+
{
|
|
57
|
+
Method method = { .name = name, .params = params, .access = access, .type = type, .id = id };
|
|
58
|
+
mMethods << method;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
void ForeignClass::addSignal(const QByteArray &name, std::size_t id, const QList<QByteArray> ¶ms)
|
|
62
|
+
{
|
|
63
|
+
addMethod(name, id, params, Method::Access::Protected, Method::Type::Signal);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
void ForeignClass::addProperty(const QByteArray &name, std::size_t getterId, std::size_t setterId, Property::Flags flags, bool hasNotifySignal,std::size_t notifySignalId)
|
|
67
|
+
{
|
|
68
|
+
Property property = { .name = name, .flags = flags, .setterId = setterId, .getterId = getterId, .hasNotifySignal = hasNotifySignal, .notifySignalId = notifySignalId};
|
|
69
|
+
mProperties << property;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <QVariant>
|
|
4
|
+
#include <QMetaMethod>
|
|
5
|
+
#include <QMetaProperty>
|
|
6
|
+
#include <QFlag>
|
|
7
|
+
#include "common.h"
|
|
8
|
+
|
|
9
|
+
class QByteArray;
|
|
10
|
+
|
|
11
|
+
namespace RubyQml {
|
|
12
|
+
|
|
13
|
+
class ForeignObject;
|
|
14
|
+
|
|
15
|
+
class ForeignClass
|
|
16
|
+
{
|
|
17
|
+
public:
|
|
18
|
+
ForeignClass();
|
|
19
|
+
virtual ~ForeignClass();
|
|
20
|
+
|
|
21
|
+
struct Method
|
|
22
|
+
{
|
|
23
|
+
enum class Access
|
|
24
|
+
{
|
|
25
|
+
Private,
|
|
26
|
+
Protected,
|
|
27
|
+
Public
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
enum class Type
|
|
31
|
+
{
|
|
32
|
+
Method,
|
|
33
|
+
Signal
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
QByteArray name;
|
|
37
|
+
QList<QByteArray> params;
|
|
38
|
+
Access access;
|
|
39
|
+
Type type;
|
|
40
|
+
std::size_t id;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
struct Property
|
|
44
|
+
{
|
|
45
|
+
enum class Flag
|
|
46
|
+
{
|
|
47
|
+
Readable = 1,
|
|
48
|
+
Writable = 1 << 1,
|
|
49
|
+
Constant = 1 << 2,
|
|
50
|
+
};
|
|
51
|
+
Q_DECLARE_FLAGS(Flags, Flag)
|
|
52
|
+
|
|
53
|
+
QByteArray name;
|
|
54
|
+
Flags flags;
|
|
55
|
+
std::size_t setterId;
|
|
56
|
+
std::size_t getterId;
|
|
57
|
+
bool hasNotifySignal;
|
|
58
|
+
std::size_t notifySignalId;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
QByteArray className() const { return mClassName; }
|
|
62
|
+
QList<Method> methods() const { return mMethods; }
|
|
63
|
+
QList<Method> signalMethods() const;
|
|
64
|
+
QList<Method> nonSignalMethods() const;
|
|
65
|
+
QList<Property> properties() const { return mProperties; }
|
|
66
|
+
|
|
67
|
+
void setClassName(const QByteArray &name) { mClassName = name; }
|
|
68
|
+
void addMethod(const QByteArray &name, std::size_t id, const QList<QByteArray> ¶ms, Method::Access access = Method::Access::Public, Method::Type type = Method::Type::Method);
|
|
69
|
+
void addSignal(const QByteArray &name, std::size_t id, const QList<QByteArray> ¶ms);
|
|
70
|
+
void addProperty(const QByteArray &name, std::size_t getterId, std::size_t setterId, Property::Flags flags, bool hasNotifySignal = false, std::size_t notifySignalId = 0);
|
|
71
|
+
|
|
72
|
+
virtual QVariant callMethod(ForeignObject *obj, size_t id, const QVariantList &args);
|
|
73
|
+
virtual void setProperty(ForeignObject *obj, size_t id, const QVariant &value);
|
|
74
|
+
virtual QVariant getProperty(ForeignObject *obj, size_t id);
|
|
75
|
+
|
|
76
|
+
protected:
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
private:
|
|
80
|
+
|
|
81
|
+
QByteArray mClassName;
|
|
82
|
+
QList<Method> mMethods;
|
|
83
|
+
QList<Property> mProperties;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
Q_DECLARE_OPERATORS_FOR_FLAGS(ForeignClass::Property::Flags)
|
|
87
|
+
|
|
88
|
+
} // namespace RubyQml
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
#include "foreignmetaobject.h"
|
|
2
|
+
#include "foreignclass.h"
|
|
3
|
+
#include "foreignobject.h"
|
|
4
|
+
#include <QQueue>
|
|
5
|
+
#include <QDebug>
|
|
6
|
+
#include <QQmlProperty>
|
|
7
|
+
#include <private/qmetaobject_p.h>
|
|
8
|
+
|
|
9
|
+
namespace RubyQml {
|
|
10
|
+
|
|
11
|
+
class ForeignMetaObject::StringPool
|
|
12
|
+
{
|
|
13
|
+
public:
|
|
14
|
+
int intern(const QByteArray &str) {
|
|
15
|
+
int size = mStrings.size();
|
|
16
|
+
for (int i = 0; i < size; ++i) {
|
|
17
|
+
if (mStrings[i] == str)
|
|
18
|
+
return i;
|
|
19
|
+
}
|
|
20
|
+
mStrings << str;
|
|
21
|
+
return size;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
QVector<uint8_t> toMetaStringData()
|
|
25
|
+
{
|
|
26
|
+
int count = mStrings.size();
|
|
27
|
+
int size = sizeof(QByteArrayData) * count;
|
|
28
|
+
for (const auto &str : mStrings) {
|
|
29
|
+
size += str.size() + 1;
|
|
30
|
+
}
|
|
31
|
+
QVector<uint8_t> data(size);
|
|
32
|
+
auto arrayDatas = reinterpret_cast<QArrayData *>(data.data());
|
|
33
|
+
auto stringData = reinterpret_cast<char *>(data.data() + sizeof(QByteArrayData) * count);
|
|
34
|
+
|
|
35
|
+
int stringOffset = 0;
|
|
36
|
+
|
|
37
|
+
for (int i = 0; i < count; ++i) {
|
|
38
|
+
const auto &string = mStrings[i];
|
|
39
|
+
auto size = string.size();
|
|
40
|
+
|
|
41
|
+
// write array data
|
|
42
|
+
auto arrayDataOffset = stringOffset + sizeof(QByteArrayData) * (count - i);
|
|
43
|
+
new(arrayDatas + i) QArrayData { Q_REFCOUNT_INITIALIZE_STATIC, size, 0, 0, qptrdiff(arrayDataOffset) };
|
|
44
|
+
|
|
45
|
+
// write string data
|
|
46
|
+
strcpy(stringData + stringOffset, string.data());
|
|
47
|
+
stringOffset += string.size() + 1;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return data;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private:
|
|
54
|
+
QList<QByteArray> mStrings;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
ForeignMetaObject::ForeignMetaObject(const SP<ForeignClass> &klass, const SP<ForeignMetaObject> &superMetaObject) :
|
|
58
|
+
mForeignClass(klass),
|
|
59
|
+
mSuperMetaObject(superMetaObject)
|
|
60
|
+
{
|
|
61
|
+
buildData();
|
|
62
|
+
|
|
63
|
+
d.superdata = mSuperMetaObject ? mSuperMetaObject.get() : &QObject::staticMetaObject;
|
|
64
|
+
d.stringdata = reinterpret_cast<const QByteArrayData *>(mStringData.data());
|
|
65
|
+
d.data = mData.data();
|
|
66
|
+
d.static_metacall = nullptr;
|
|
67
|
+
d.relatedMetaObjects = nullptr;
|
|
68
|
+
d.extradata = nullptr;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
void ForeignMetaObject::emitSignal(ForeignObject *obj, std::size_t id, const QVariantList &args)
|
|
72
|
+
{
|
|
73
|
+
auto metamethod = method(mSignalIndexHash[id] + methodOffset());
|
|
74
|
+
if (metamethod.parameterCount() != args.size()) {
|
|
75
|
+
qWarning() << "wrong number of signal arguments";
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
QVariantList argsToPass = args;
|
|
79
|
+
while (argsToPass.size() < 10) {
|
|
80
|
+
argsToPass << QVariant();
|
|
81
|
+
}
|
|
82
|
+
metamethod.invoke(obj,
|
|
83
|
+
Q_ARG(QVariant, argsToPass[0]),
|
|
84
|
+
Q_ARG(QVariant, argsToPass[1]),
|
|
85
|
+
Q_ARG(QVariant, argsToPass[2]),
|
|
86
|
+
Q_ARG(QVariant, argsToPass[3]),
|
|
87
|
+
Q_ARG(QVariant, argsToPass[4]),
|
|
88
|
+
Q_ARG(QVariant, argsToPass[5]),
|
|
89
|
+
Q_ARG(QVariant, argsToPass[6]),
|
|
90
|
+
Q_ARG(QVariant, argsToPass[7]),
|
|
91
|
+
Q_ARG(QVariant, argsToPass[8]),
|
|
92
|
+
Q_ARG(QVariant, argsToPass[9]));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
int ForeignMetaObject::dynamicMetaCall(ForeignObject *obj, QMetaObject::Call call, int index, void **argv)
|
|
96
|
+
{
|
|
97
|
+
if (mSuperMetaObject) {
|
|
98
|
+
index = mSuperMetaObject->dynamicMetaCall(obj, call, index, argv);
|
|
99
|
+
} else {
|
|
100
|
+
index = obj->QObject::qt_metacall(call, index, argv);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (index < 0) {
|
|
104
|
+
return index;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
switch (call) {
|
|
108
|
+
case QMetaObject::InvokeMetaMethod: {
|
|
109
|
+
if (index < mMethodCount) {
|
|
110
|
+
if (index < mSignalCount) {
|
|
111
|
+
QMetaObject::activate(obj, this, index, argv);
|
|
112
|
+
} else {
|
|
113
|
+
QVariantList args;
|
|
114
|
+
std::transform(argv + 1, argv + 1 + mMethodArities[index], std::back_inserter(args), [](void *arg) {
|
|
115
|
+
return *reinterpret_cast<QVariant *>(arg);
|
|
116
|
+
});
|
|
117
|
+
auto result = mForeignClass->callMethod(obj, mMethodIds[index], args);
|
|
118
|
+
if (argv[0]) {
|
|
119
|
+
*static_cast<QVariant *>(argv[0]) = result;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
index -= mMethodCount;
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
case QMetaObject::ReadProperty: {
|
|
127
|
+
if (index < mPropertyCount) {
|
|
128
|
+
auto result = mForeignClass->getProperty(obj, mPropertyGetterIds[index]);
|
|
129
|
+
*static_cast<QVariant *>(argv[0]) = result;
|
|
130
|
+
}
|
|
131
|
+
index -= mPropertyCount;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
case QMetaObject::WriteProperty: {
|
|
135
|
+
if (index < mPropertyCount) {
|
|
136
|
+
auto variant = *static_cast<QVariant *>(argv[0]);
|
|
137
|
+
mForeignClass->setProperty(obj, mPropertySetterIds[index], variant);
|
|
138
|
+
}
|
|
139
|
+
index -= mPropertyCount;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
case QMetaObject::ResetProperty:
|
|
143
|
+
case QMetaObject::QueryPropertyDesignable:
|
|
144
|
+
case QMetaObject::QueryPropertyScriptable:
|
|
145
|
+
case QMetaObject::QueryPropertyStored:
|
|
146
|
+
case QMetaObject::QueryPropertyEditable:
|
|
147
|
+
case QMetaObject::QueryPropertyUser: {
|
|
148
|
+
index -= mPropertyCount;
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
case QMetaObject::RegisterPropertyMetaType: {
|
|
152
|
+
if (index < mPropertyCount) {
|
|
153
|
+
*static_cast<int *>(argv[0]) = -1;
|
|
154
|
+
}
|
|
155
|
+
index -= mPropertyCount;
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
default:
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return index;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
void ForeignMetaObject::buildData()
|
|
166
|
+
{
|
|
167
|
+
auto klass = mForeignClass;
|
|
168
|
+
int index = 0;
|
|
169
|
+
mMethodCount = klass->methods().size();
|
|
170
|
+
for (const auto &signal : klass->signalMethods()) {
|
|
171
|
+
mMethodIds << signal.id;
|
|
172
|
+
mMethodArities << signal.params.size();
|
|
173
|
+
mSignalIndexHash[signal.id] = index++;
|
|
174
|
+
}
|
|
175
|
+
mSignalCount = klass->signalMethods().size();
|
|
176
|
+
for (const auto &method : klass->nonSignalMethods()) {
|
|
177
|
+
mMethodIds << method.id;
|
|
178
|
+
mMethodArities << method.params.size();
|
|
179
|
+
}
|
|
180
|
+
mPropertyCount = klass->properties().size();
|
|
181
|
+
for (const auto &property : klass->properties()) {
|
|
182
|
+
mPropertySetterIds << property.setterId;
|
|
183
|
+
mPropertyGetterIds << property.getterId;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
StringPool stringPool;
|
|
187
|
+
mData = writeMetaData(stringPool);
|
|
188
|
+
mStringData = stringPool.toMetaStringData();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
QVector<uint> ForeignMetaObject::writeMetaData(StringPool &stringPool)
|
|
192
|
+
{
|
|
193
|
+
auto klass = mForeignClass;
|
|
194
|
+
|
|
195
|
+
int methodDataSize = 0;
|
|
196
|
+
|
|
197
|
+
for (const auto &method : klass->methods()) {
|
|
198
|
+
methodDataSize += 5 + 1 + method.params.size() * 2;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
QVector<uint> metaData;
|
|
202
|
+
|
|
203
|
+
auto markIndex = [&]() {
|
|
204
|
+
auto index = metaData.size();
|
|
205
|
+
metaData << 0;
|
|
206
|
+
return index;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
auto writeCurrentPos = [&](int markedIndex) {
|
|
210
|
+
metaData[markedIndex] = metaData.size();
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// write header //
|
|
214
|
+
|
|
215
|
+
metaData << 7; // revision
|
|
216
|
+
metaData << stringPool.intern(klass->className()); // classname
|
|
217
|
+
metaData << 0 << 0; // classinfo
|
|
218
|
+
|
|
219
|
+
auto methods = klass->methods();
|
|
220
|
+
auto signalMethods = klass->signalMethods();
|
|
221
|
+
auto nonSignalMethods = klass->nonSignalMethods();
|
|
222
|
+
|
|
223
|
+
// methods
|
|
224
|
+
metaData << (methods.size());
|
|
225
|
+
int methodInfoPosIndex = markIndex();
|
|
226
|
+
|
|
227
|
+
auto properties = klass->properties();
|
|
228
|
+
|
|
229
|
+
// properties
|
|
230
|
+
metaData << properties.size();
|
|
231
|
+
int propertyInfoPosIndex = markIndex();
|
|
232
|
+
|
|
233
|
+
metaData << 0 << 0; // enums
|
|
234
|
+
metaData << 0 << 0; // constructors
|
|
235
|
+
metaData << 0; // flags
|
|
236
|
+
metaData << signalMethods.size(); // signal count
|
|
237
|
+
|
|
238
|
+
// write method info //
|
|
239
|
+
|
|
240
|
+
writeCurrentPos(methodInfoPosIndex);
|
|
241
|
+
|
|
242
|
+
QQueue<int> parameterInfoPosIndexes;
|
|
243
|
+
|
|
244
|
+
auto addMethodInfo = [&](const ForeignClass::Method &method) {
|
|
245
|
+
metaData << stringPool.intern(method.name); // name
|
|
246
|
+
metaData << method.params.size(); // argc
|
|
247
|
+
parameterInfoPosIndexes.enqueue(markIndex()); // parameters
|
|
248
|
+
metaData << 2; // tag
|
|
249
|
+
int flags = 0;
|
|
250
|
+
if (method.type == ForeignClass::Method::Type::Signal) {
|
|
251
|
+
flags |= AccessProtected;
|
|
252
|
+
flags |= MethodSignal;
|
|
253
|
+
} else {
|
|
254
|
+
flags |= AccessPublic;
|
|
255
|
+
}
|
|
256
|
+
metaData << flags; // flags
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
for (const auto &signal : signalMethods) {
|
|
260
|
+
addMethodInfo(signal);
|
|
261
|
+
}
|
|
262
|
+
for (const auto &method : nonSignalMethods) {
|
|
263
|
+
addMethodInfo(method);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
auto addParametersInfo = [&](const ForeignClass::Method &method) {
|
|
267
|
+
writeCurrentPos(parameterInfoPosIndexes.dequeue());
|
|
268
|
+
metaData << QMetaType::QVariant;
|
|
269
|
+
for (int i = 0; i < method.params.size(); ++i) {
|
|
270
|
+
metaData << QMetaType::QVariant;
|
|
271
|
+
}
|
|
272
|
+
for (const auto ¶m : method.params) {
|
|
273
|
+
metaData << stringPool.intern(param);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
for (const auto &signal : signalMethods) {
|
|
278
|
+
addParametersInfo(signal);
|
|
279
|
+
}
|
|
280
|
+
for (const auto &method : nonSignalMethods) {
|
|
281
|
+
addParametersInfo(method);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// write property info //
|
|
285
|
+
|
|
286
|
+
writeCurrentPos(propertyInfoPosIndex);
|
|
287
|
+
|
|
288
|
+
for (const auto &property : properties) {
|
|
289
|
+
metaData << stringPool.intern(property.name);
|
|
290
|
+
metaData << QMetaType::QVariant;
|
|
291
|
+
int flags = Notify | ResolveEditable | Stored | Scriptable | Designable;
|
|
292
|
+
if (property.flags & ForeignClass::Property::Flag::Writable) {
|
|
293
|
+
flags |= Writable;
|
|
294
|
+
}
|
|
295
|
+
if (property.flags & ForeignClass::Property::Flag::Readable) {
|
|
296
|
+
flags |= Readable;
|
|
297
|
+
}
|
|
298
|
+
if (property.flags & ForeignClass::Property::Flag::Constant) {
|
|
299
|
+
flags |= Constant;
|
|
300
|
+
}
|
|
301
|
+
metaData << flags;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
for (const auto &property : properties) {
|
|
305
|
+
int signalIndex;
|
|
306
|
+
if (property.hasNotifySignal) {
|
|
307
|
+
signalIndex = mSignalIndexHash[property.notifySignalId];
|
|
308
|
+
} else {
|
|
309
|
+
signalIndex = -1;
|
|
310
|
+
}
|
|
311
|
+
metaData << signalIndex;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// end of data //
|
|
315
|
+
|
|
316
|
+
metaData << 0;
|
|
317
|
+
|
|
318
|
+
return metaData;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
void ForeignMetaObject::dump()
|
|
322
|
+
{
|
|
323
|
+
qDebug() << "-- dumping ForeignClass::MetaObject" << className();
|
|
324
|
+
qDebug() << " -- methods";
|
|
325
|
+
for (int i = 0; i < methodCount(); ++i) {
|
|
326
|
+
auto m = method(i);
|
|
327
|
+
qDebug() << "name:" << m.name();
|
|
328
|
+
qDebug() << "return type:" << QMetaType::typeName(m.returnType());
|
|
329
|
+
qDebug() << "param types:" << m.parameterTypes();
|
|
330
|
+
qDebug() << "param names" << m.parameterNames();
|
|
331
|
+
qDebug() << "method type" << m.methodType();
|
|
332
|
+
qDebug() << "attributes" << m.attributes();
|
|
333
|
+
}
|
|
334
|
+
qDebug() << " -- properties";
|
|
335
|
+
for (int i = 0; i < propertyCount(); ++i) {
|
|
336
|
+
auto p = property(i);
|
|
337
|
+
qDebug() << "name:" << p.name();
|
|
338
|
+
qDebug() << "notify signal:" << p.notifySignal().name();
|
|
339
|
+
qDebug() << "writable" << p.isWritable();
|
|
340
|
+
qDebug() << "readable" << p.isReadable();
|
|
341
|
+
qDebug() << "constant" << p.isConstant();
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
} // namespace RubyQml
|