qml 0.0.7 → 1.0.0

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.
Files changed (296) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -0
  3. data/.travis.yml +5 -9
  4. data/LICENSE.txt +1 -1
  5. data/README.md +84 -114
  6. data/changes.md +5 -0
  7. data/examples/fizzbuzz/fizzbuzz.rb +3 -4
  8. data/examples/todo_array/todo_array.rb +4 -4
  9. data/examples/todo_sequel/todo_sequel.rb +7 -7
  10. data/examples/twitter/twitter.rb +5 -3
  11. data/ext/qml/application.c +88 -0
  12. data/ext/qml/application.h +9 -0
  13. data/ext/qml/component.c +89 -0
  14. data/ext/qml/component.h +10 -0
  15. data/ext/qml/conversion.c +60 -0
  16. data/ext/qml/conversion.h +8 -0
  17. data/ext/qml/dispatcher.c +31 -0
  18. data/ext/qml/dispatcher.h +7 -0
  19. data/ext/qml/engine.c +135 -0
  20. data/ext/qml/engine.h +10 -0
  21. data/ext/qml/exporter.c +93 -0
  22. data/ext/qml/exporter.h +7 -0
  23. data/ext/qml/extconf.rb +38 -97
  24. data/ext/qml/interface.c +156 -0
  25. data/ext/qml/interface.h +11 -0
  26. data/ext/qml/js_array.c +47 -0
  27. data/ext/qml/js_array.h +7 -0
  28. data/ext/qml/js_function.c +109 -0
  29. data/ext/qml/js_function.h +7 -0
  30. data/ext/qml/js_object.c +284 -0
  31. data/ext/qml/js_object.h +19 -0
  32. data/ext/qml/js_wrapper.c +19 -0
  33. data/ext/qml/js_wrapper.h +7 -0
  34. data/ext/qml/lib/libqmlbind/.gitignore +38 -0
  35. data/ext/qml/lib/libqmlbind/.gitmodules +3 -0
  36. data/ext/qml/lib/libqmlbind/.travis.yml +14 -0
  37. data/ext/qml/lib/libqmlbind/LICENSE.txt +22 -0
  38. data/ext/qml/lib/libqmlbind/libqmlbind.pro +3 -0
  39. data/ext/qml/lib/libqmlbind/qmlbind/include/qmlbind.h +14 -0
  40. data/ext/qml/lib/libqmlbind/qmlbind/include/qmlbind/application.h +18 -0
  41. data/ext/qml/lib/libqmlbind/qmlbind/include/qmlbind/component.h +21 -0
  42. data/ext/qml/lib/libqmlbind/qmlbind/include/qmlbind/engine.h +34 -0
  43. data/ext/qml/lib/libqmlbind/qmlbind/include/qmlbind/exporter.h +37 -0
  44. data/ext/qml/lib/libqmlbind/qmlbind/include/qmlbind/interface.h +16 -0
  45. data/ext/qml/lib/libqmlbind/qmlbind/include/qmlbind/iterator.h +19 -0
  46. data/ext/qml/lib/libqmlbind/qmlbind/include/qmlbind/metaobject.h +13 -0
  47. data/ext/qml/lib/libqmlbind/qmlbind/include/qmlbind/plugin.h +17 -0
  48. data/ext/qml/lib/libqmlbind/qmlbind/include/qmlbind/qmlbind_global.h +78 -0
  49. data/ext/qml/lib/libqmlbind/qmlbind/include/qmlbind/register.h +17 -0
  50. data/ext/qml/lib/libqmlbind/qmlbind/include/qmlbind/signal_emitter.h +15 -0
  51. data/ext/qml/lib/libqmlbind/qmlbind/include/qmlbind/string.h +15 -0
  52. data/ext/qml/lib/libqmlbind/qmlbind/include/qmlbind/value.h +100 -0
  53. data/ext/qml/lib/libqmlbind/qmlbind/qmlbind.pro +62 -0
  54. data/ext/qml/lib/libqmlbind/qmlbind/src/api_application.cpp +103 -0
  55. data/ext/qml/lib/libqmlbind/qmlbind/src/api_component.cpp +54 -0
  56. data/ext/qml/lib/libqmlbind/qmlbind/src/api_engine.cpp +65 -0
  57. data/ext/qml/lib/libqmlbind/qmlbind/src/api_exporter.cpp +52 -0
  58. data/ext/qml/lib/libqmlbind/qmlbind/src/api_interface.cpp +19 -0
  59. data/ext/qml/lib/libqmlbind/qmlbind/src/api_iterator.cpp +32 -0
  60. data/ext/qml/lib/libqmlbind/qmlbind/src/api_metaobject.cpp +19 -0
  61. data/ext/qml/lib/libqmlbind/qmlbind/src/api_plugin.cpp +27 -0
  62. data/ext/qml/lib/libqmlbind/qmlbind/src/api_register.cpp +17 -0
  63. data/ext/qml/lib/libqmlbind/qmlbind/src/api_signal_emitter.cpp +27 -0
  64. data/ext/qml/lib/libqmlbind/qmlbind/src/api_string.cpp +22 -0
  65. data/ext/qml/lib/libqmlbind/qmlbind/src/api_value.cpp +215 -0
  66. data/ext/qml/lib/libqmlbind/qmlbind/src/backref.cpp +54 -0
  67. data/ext/qml/lib/libqmlbind/qmlbind/src/backref.h +29 -0
  68. data/ext/qml/lib/libqmlbind/qmlbind/src/engine.cpp +32 -0
  69. data/ext/qml/lib/libqmlbind/qmlbind/src/engine.h +27 -0
  70. data/ext/qml/lib/libqmlbind/qmlbind/src/exporter.cpp +73 -0
  71. data/ext/qml/lib/libqmlbind/qmlbind/src/exporter.h +46 -0
  72. data/ext/qml/lib/libqmlbind/qmlbind/src/interface.cpp +75 -0
  73. data/ext/qml/lib/libqmlbind/qmlbind/src/interface.h +37 -0
  74. data/ext/qml/lib/libqmlbind/qmlbind/src/metaobject.cpp +101 -0
  75. data/ext/qml/lib/libqmlbind/qmlbind/src/metaobject.h +29 -0
  76. data/ext/qml/lib/libqmlbind/qmlbind/src/signalemitter.cpp +33 -0
  77. data/ext/qml/lib/libqmlbind/qmlbind/src/signalemitter.h +25 -0
  78. data/ext/qml/lib/libqmlbind/qmlbind/src/ticktimer.cpp +15 -0
  79. data/ext/qml/lib/libqmlbind/qmlbind/src/ticktimer.h +19 -0
  80. data/ext/qml/lib/libqmlbind/qmlbind/src/typeregisterer.cpp +112 -0
  81. data/ext/qml/lib/libqmlbind/qmlbind/src/typeregisterer.h +28 -0
  82. data/ext/qml/lib/libqmlbind/qmlbind/src/util.h +13 -0
  83. data/ext/qml/lib/libqmlbind/qmlbind/src/wrapper.cpp +23 -0
  84. data/ext/qml/lib/libqmlbind/qmlbind/src/wrapper.h +29 -0
  85. data/ext/qml/lib/libqmlbind/readme.md +14 -0
  86. data/ext/qml/lib/libqmlbind/test/api.c +1 -0
  87. data/ext/qml/lib/libqmlbind/test/application_test.cpp +16 -0
  88. data/ext/qml/lib/libqmlbind/test/component_test.cpp +57 -0
  89. data/ext/qml/lib/libqmlbind/test/engine_test.cpp +94 -0
  90. data/ext/qml/lib/libqmlbind/test/exporter_test.cpp +312 -0
  91. data/ext/qml/lib/libqmlbind/test/fixtures/emptyhandlers.cpp +36 -0
  92. data/ext/qml/lib/libqmlbind/test/fixtures/emptyhandlers.h +6 -0
  93. data/ext/qml/lib/libqmlbind/test/fixtures/test.qml +5 -0
  94. data/ext/qml/lib/libqmlbind/test/fixtures/testmodule/qmldir +2 -0
  95. data/ext/qml/lib/libqmlbind/test/fixtures/testmodule/test.qml +5 -0
  96. data/ext/qml/lib/libqmlbind/test/iterator_test.cpp +37 -0
  97. data/ext/qml/lib/libqmlbind/test/main.cpp +11 -0
  98. data/ext/qml/lib/libqmlbind/test/plugin_test.cpp +41 -0
  99. data/ext/qml/lib/libqmlbind/test/test.pro +26 -0
  100. data/ext/qml/lib/libqmlbind/test/test_helper.h +20 -0
  101. data/ext/qml/lib/libqmlbind/test/value_test.cpp +252 -0
  102. data/ext/qml/lib/libqmlbind/testplugin/testplugin.cpp +11 -0
  103. data/ext/qml/lib/libqmlbind/testplugin/testplugin.h +21 -0
  104. data/ext/qml/lib/libqmlbind/testplugin/testplugin.json +3 -0
  105. data/ext/qml/lib/libqmlbind/testplugin/testplugin.pro +21 -0
  106. data/ext/qml/meta_object.c +81 -0
  107. data/ext/qml/meta_object.h +8 -0
  108. data/ext/qml/plugin_loader.c +71 -0
  109. data/ext/qml/plugin_loader.h +7 -0
  110. data/ext/qml/qml.c +95 -0
  111. data/ext/qml/qml.h +10 -0
  112. data/ext/qml/rubyqml-plugin/listmodel.cpp +102 -0
  113. data/ext/qml/rubyqml-plugin/listmodel.h +37 -0
  114. data/ext/qml/rubyqml-plugin/rubyqml-plugin.pro +19 -0
  115. data/ext/qml/rubyqml-plugin/rubyqmlplugin.cpp +25 -0
  116. data/ext/qml/rubyqml-plugin/rubyqmlplugin.h +19 -0
  117. data/ext/qml/signal_emitter.c +71 -0
  118. data/ext/qml/signal_emitter.h +9 -0
  119. data/lib/qml.rb +11 -10
  120. data/lib/qml/access.rb +64 -86
  121. data/lib/qml/application.rb +20 -71
  122. data/lib/qml/component.rb +41 -33
  123. data/lib/qml/core_ext.rb +1 -0
  124. data/lib/qml/core_ext/to_qml.rb +70 -0
  125. data/lib/qml/data.rb +1 -0
  126. data/lib/qml/data/array_model.rb +99 -101
  127. data/lib/qml/data/list_model.rb +107 -131
  128. data/lib/qml/data/list_model_access.rb +44 -0
  129. data/lib/qml/data/query_model.rb +45 -47
  130. data/lib/qml/dispatcher.rb +5 -13
  131. data/lib/qml/engine.rb +9 -58
  132. data/lib/qml/errors.rb +0 -21
  133. data/lib/qml/interface.rb +21 -0
  134. data/lib/qml/js_array.rb +8 -0
  135. data/lib/qml/js_object.rb +69 -0
  136. data/lib/qml/js_util.rb +18 -0
  137. data/lib/qml/plugin_loader.rb +1 -13
  138. data/lib/qml/plugins.rb +3 -17
  139. data/lib/qml/proc_access.rb +28 -0
  140. data/lib/qml/qt.rb +21 -3
  141. data/lib/qml/reactive.rb +147 -8
  142. data/lib/qml/signal.rb +67 -0
  143. data/lib/qml/version.rb +1 -1
  144. data/qml.gemspec +8 -2
  145. data/spec/qml/access_spec.rb +33 -120
  146. data/spec/qml/application_spec.rb +11 -24
  147. data/spec/qml/component_spec.rb +4 -4
  148. data/spec/qml/data/array_model_spec.rb +2 -2
  149. data/spec/qml/data/list_model_spec.rb +2 -2
  150. data/spec/qml/data/query_model_spec.rb +4 -4
  151. data/spec/qml/engine_spec.rb +23 -21
  152. data/spec/qml/interface_spec.rb +20 -0
  153. data/spec/qml/js_array_spec.rb +29 -0
  154. data/spec/qml/js_function_spec.rb +32 -0
  155. data/spec/qml/js_object_spec.rb +113 -0
  156. data/spec/qml/plugin_loader_spec.rb +9 -11
  157. data/spec/qml/qt_spec.rb +9 -0
  158. data/spec/qml/reactive_spec.rb +37 -0
  159. data/spec/qml/signal_connect_spec.rb +27 -0
  160. data/spec/qml/signal_spec.rb +73 -0
  161. data/spec/qml/to_qml_spec.rb +76 -0
  162. data/spec/shared/qml/access_example.rb +21 -0
  163. data/spec/shared/qml/data/list_model.rb +12 -13
  164. data/spec/spec_helper.rb +2 -3
  165. metadata +141 -166
  166. data/examples/imageprovider/imageprovider.rb +0 -57
  167. data/examples/imageprovider/main.qml +0 -51
  168. data/ext/qml/accessclass.cpp +0 -65
  169. data/ext/qml/accessclass.h +0 -19
  170. data/ext/qml/accessobject.cpp +0 -30
  171. data/ext/qml/accessobject.h +0 -22
  172. data/ext/qml/common.h +0 -18
  173. data/ext/qml/conversionerror.h +0 -14
  174. data/ext/qml/ext_accesswrapperfactory.cpp +0 -75
  175. data/ext/qml/ext_accesswrapperfactory.h +0 -39
  176. data/ext/qml/ext_anywrapper.cpp +0 -34
  177. data/ext/qml/ext_anywrapper.h +0 -23
  178. data/ext/qml/ext_kernel.cpp +0 -81
  179. data/ext/qml/ext_kernel.h +0 -9
  180. data/ext/qml/ext_metaobject.cpp +0 -399
  181. data/ext/qml/ext_metaobject.h +0 -60
  182. data/ext/qml/ext_pluginloader.cpp +0 -53
  183. data/ext/qml/ext_pluginloader.h +0 -30
  184. data/ext/qml/ext_pointer.cpp +0 -132
  185. data/ext/qml/ext_pointer.h +0 -41
  186. data/ext/qml/ext_testutil.cpp +0 -40
  187. data/ext/qml/ext_testutil.h +0 -9
  188. data/ext/qml/foreignclass.cpp +0 -72
  189. data/ext/qml/foreignclass.h +0 -88
  190. data/ext/qml/foreignmetaobject.cpp +0 -345
  191. data/ext/qml/foreignmetaobject.h +0 -46
  192. data/ext/qml/foreignobject.cpp +0 -22
  193. data/ext/qml/foreignobject.h +0 -21
  194. data/ext/qml/functioninfo.h +0 -16
  195. data/ext/qml/init.cpp +0 -67
  196. data/ext/qml/kernel.cpp +0 -39
  197. data/ext/qml/kernel.h +0 -32
  198. data/ext/qml/listmodel.cpp +0 -137
  199. data/ext/qml/listmodel.h +0 -45
  200. data/ext/qml/markable.h +0 -12
  201. data/ext/qml/objectdata.cpp +0 -26
  202. data/ext/qml/objectdata.h +0 -20
  203. data/ext/qml/objectgc.cpp +0 -69
  204. data/ext/qml/objectgc.h +0 -28
  205. data/ext/qml/plugins/core/applicationextension.cpp +0 -29
  206. data/ext/qml/plugins/core/applicationextension.h +0 -25
  207. data/ext/qml/plugins/core/componentextension.cpp +0 -41
  208. data/ext/qml/plugins/core/componentextension.h +0 -28
  209. data/ext/qml/plugins/core/contextextension.cpp +0 -39
  210. data/ext/qml/plugins/core/contextextension.h +0 -29
  211. data/ext/qml/plugins/core/core.pro +0 -29
  212. data/ext/qml/plugins/core/coreplugin.cpp +0 -87
  213. data/ext/qml/plugins/core/coreplugin.h +0 -49
  214. data/ext/qml/plugins/core/engineextension.cpp +0 -43
  215. data/ext/qml/plugins/core/engineextension.h +0 -31
  216. data/ext/qml/plugins/core/imageprovider.cpp +0 -38
  217. data/ext/qml/plugins/core/imageprovider.h +0 -18
  218. data/ext/qml/plugins/core/imagerequestpromise.cpp +0 -19
  219. data/ext/qml/plugins/core/imagerequestpromise.h +0 -21
  220. data/ext/qml/plugins/core/qmlexception.cpp +0 -11
  221. data/ext/qml/plugins/core/qmlexception.h +0 -17
  222. data/ext/qml/plugins/testutil/imageprovidertest.cpp +0 -40
  223. data/ext/qml/plugins/testutil/imageprovidertest.h +0 -17
  224. data/ext/qml/plugins/testutil/objectlifechecker.cpp +0 -17
  225. data/ext/qml/plugins/testutil/objectlifechecker.h +0 -24
  226. data/ext/qml/plugins/testutil/ownershiptest.cpp +0 -26
  227. data/ext/qml/plugins/testutil/ownershiptest.h +0 -30
  228. data/ext/qml/plugins/testutil/testobject.cpp +0 -6
  229. data/ext/qml/plugins/testutil/testobject.h +0 -108
  230. data/ext/qml/plugins/testutil/testobjectsubclass.cpp +0 -10
  231. data/ext/qml/plugins/testutil/testobjectsubclass.h +0 -19
  232. data/ext/qml/plugins/testutil/testutil.pro +0 -22
  233. data/ext/qml/plugins/testutil/testutilplugin.cpp +0 -55
  234. data/ext/qml/plugins/testutil/testutilplugin.h +0 -36
  235. data/ext/qml/qmltyperegisterer.cpp +0 -74
  236. data/ext/qml/qmltyperegisterer.h +0 -30
  237. data/ext/qml/rubyclass.cpp +0 -82
  238. data/ext/qml/rubyclass.h +0 -230
  239. data/ext/qml/rubyvalue.cpp +0 -656
  240. data/ext/qml/rubyvalue.h +0 -224
  241. data/ext/qml/signalforwarder.cpp +0 -64
  242. data/ext/qml/signalforwarder.h +0 -29
  243. data/ext/qml/util.cpp +0 -112
  244. data/ext/qml/util.h +0 -82
  245. data/ext/qml/valuereference.cpp +0 -50
  246. data/ext/qml/valuereference.h +0 -22
  247. data/ext/qml/weakvaluereference.cpp +0 -51
  248. data/ext/qml/weakvaluereference.h +0 -21
  249. data/lib/qml/context.rb +0 -71
  250. data/lib/qml/data/error.rb +0 -5
  251. data/lib/qml/dispatchable.rb +0 -34
  252. data/lib/qml/error_converter.rb +0 -16
  253. data/lib/qml/geometry.rb +0 -3
  254. data/lib/qml/geometry/point.rb +0 -5
  255. data/lib/qml/geometry/rectangle.rb +0 -5
  256. data/lib/qml/geometry/size.rb +0 -5
  257. data/lib/qml/image_provider.rb +0 -87
  258. data/lib/qml/init.rb +0 -29
  259. data/lib/qml/meta_object.rb +0 -20
  260. data/lib/qml/models.rb +0 -1
  261. data/lib/qml/qt_classes.rb +0 -9
  262. data/lib/qml/qt_object_base.rb +0 -233
  263. data/lib/qml/reactive/bindable.rb +0 -79
  264. data/lib/qml/reactive/chained_signal.rb +0 -25
  265. data/lib/qml/reactive/error.rb +0 -5
  266. data/lib/qml/reactive/object.rb +0 -293
  267. data/lib/qml/reactive/property.rb +0 -19
  268. data/lib/qml/reactive/signal.rb +0 -115
  269. data/lib/qml/reactive/signal_spy.rb +0 -27
  270. data/lib/qml/reactive/signals/map_signal.rb +0 -21
  271. data/lib/qml/reactive/signals/merge_signal.rb +0 -21
  272. data/lib/qml/reactive/signals/select_signal.rb +0 -21
  273. data/lib/qml/reactive/simple_property.rb +0 -17
  274. data/lib/qml/reactive/unbound_property.rb +0 -42
  275. data/lib/qml/reactive/unbound_signal.rb +0 -51
  276. data/lib/qml/test_util.rb +0 -1
  277. data/lib/qml/test_util/object_life_checker.rb +0 -17
  278. data/lib/qml/wrappable.rb +0 -9
  279. data/spec/qml/context_spec.rb +0 -43
  280. data/spec/qml/conversion_spec.rb +0 -60
  281. data/spec/qml/dispatchable_spec.rb +0 -26
  282. data/spec/qml/dispatcher_spec.rb +0 -71
  283. data/spec/qml/geometry/point_spec.rb +0 -4
  284. data/spec/qml/geometry/rectangle_spec.rb +0 -4
  285. data/spec/qml/geometry/size_spec.rb +0 -4
  286. data/spec/qml/image_provider_spec.rb +0 -33
  287. data/spec/qml/qt_object_base_spec.rb +0 -119
  288. data/spec/qml/reactive/object_spec.rb +0 -249
  289. data/spec/qml/reactive/property_spec.rb +0 -70
  290. data/spec/qml/reactive/signal_spec.rb +0 -191
  291. data/spec/qml/reactive/signal_spy_spec.rb +0 -26
  292. data/spec/qml/reactive/unbound_property_spec.rb +0 -40
  293. data/spec/qml/reactive/unbound_signal_spec.rb +0 -70
  294. data/spec/qml/test_object_spec.rb +0 -186
  295. data/spec/qml/wrappable_spec.rb +0 -10
  296. data/spec/shared/qml/reactive/object.rb +0 -39
@@ -0,0 +1,28 @@
1
+ #pragma once
2
+
3
+ #include <QVector>
4
+ #include <QSharedPointer>
5
+
6
+ namespace QmlBind {
7
+
8
+ class MetaObject;
9
+
10
+ class TypeRegisterer
11
+ {
12
+ public:
13
+ static TypeRegisterer &instance();
14
+ int registerType(const QSharedPointer<const MetaObject> &metaObject, const char *uri, int versionMajor, int versionMinor, const char *qmlName);
15
+
16
+ private:
17
+ typedef void (*CreationCallback)(void *);
18
+ template <int Count, int Offset = 0> struct CreationCallbacksSetter;
19
+
20
+ TypeRegisterer();
21
+ template <int Index> static void create(void *memory);
22
+ void registerType(const QSharedPointer<const MetaObject> &metaObject, CreationCallback create, const char *uri, int versionMajor, int versionMinor, const char *qmlName);
23
+
24
+ QVector<QSharedPointer<const MetaObject> > mMetaObjects;
25
+ QVector<CreationCallback> mCreationCallbacks;
26
+ };
27
+
28
+ } // namespace QmlBind
@@ -0,0 +1,13 @@
1
+ #pragma once
2
+
3
+ #include <QSharedPointer>
4
+
5
+ namespace QmlBind {
6
+
7
+ template <typename T>
8
+ QSharedPointer<T> *newSharedPointer(T *ptr)
9
+ {
10
+ return new QSharedPointer<T>(ptr);
11
+ }
12
+
13
+ }
@@ -0,0 +1,23 @@
1
+ #include "wrapper.h"
2
+ #include "metaobject.h"
3
+ #include "exporter.h"
4
+
5
+ namespace QmlBind {
6
+
7
+ Wrapper::Wrapper(const QSharedPointer<const MetaObject> &metaObject, const Backref &ref) :
8
+ mMetaObject(metaObject),
9
+ mRef(ref)
10
+ {
11
+ }
12
+
13
+ const QMetaObject *Wrapper::metaObject() const
14
+ {
15
+ return mMetaObject.data();
16
+ }
17
+
18
+ int Wrapper::qt_metacall(QMetaObject::Call call, int index, void **argv)
19
+ {
20
+ return mMetaObject->metaCall(this, call, index, argv);
21
+ }
22
+
23
+ } // namespace QmlBind
@@ -0,0 +1,29 @@
1
+ #pragma once
2
+
3
+ #include "qmlbind/qmlbind_global.h"
4
+ #include "backref.h"
5
+ #include <QObject>
6
+ #include <QSharedPointer>
7
+
8
+ namespace QmlBind {
9
+
10
+ class MetaObject;
11
+
12
+ class Wrapper : public QObject
13
+ {
14
+ public:
15
+ Wrapper(const QSharedPointer<const MetaObject> &metaObject, const Backref &ref);
16
+
17
+ const QMetaObject *metaObject() const Q_DECL_OVERRIDE;
18
+ int qt_metacall(QMetaObject::Call call, int index, void **argv) Q_DECL_OVERRIDE;
19
+
20
+ Backref backref() { return mRef; }
21
+ QSharedPointer<const MetaObject> qmlbindMetaObject() { return mMetaObject; }
22
+
23
+ private:
24
+
25
+ QSharedPointer<const MetaObject> mMetaObject;
26
+ Backref mRef;
27
+ };
28
+
29
+ } // namespace QmlBind
@@ -0,0 +1,14 @@
1
+ # libqmlbind
2
+
3
+ libqmlbind is a C library for creating QML bindings for other languages easily through exporting objects and classes to QML.
4
+
5
+ [![Build Status](https://travis-ci.org/seanchas116/libqmlbind.svg?branch=master)](https://travis-ci.org/seanchas116/libqmlbind)
6
+
7
+ ## Features
8
+
9
+ * Simple API to export objects / classes dynamically to QML
10
+ * Shared library with pure C interface
11
+ * Decouple your language bindings from Qt itself
12
+ * High portability
13
+ * Build with qmake
14
+ * No need to configure compilation flags for Qt manually
@@ -0,0 +1 @@
1
+ #include <qmlbind.h>
@@ -0,0 +1,16 @@
1
+ #include "test_helper.h"
2
+ #include "fixtures/emptyhandlers.h"
3
+ #include <qmlbind.h>
4
+
5
+ TEST_CASE("set_tick_callback")
6
+ {
7
+ static bool called;
8
+ called = false;
9
+
10
+ qmlbind_set_tick_callback([] {
11
+ called = true;
12
+ });
13
+ qmlbind_process_events();
14
+
15
+ REQUIRE(called);
16
+ }
@@ -0,0 +1,57 @@
1
+ #include "test_helper.h"
2
+ #include <qmlbind.h>
3
+ #include <string.h>
4
+
5
+ TEST_CASE("component")
6
+ {
7
+ auto engine = qmlbind_engine_new();
8
+ auto component = qmlbind_component_new(engine);
9
+
10
+ SECTION("#create")
11
+ {
12
+ SECTION("with data")
13
+ {
14
+ auto data = R"QML(
15
+ import QtQml 2.2
16
+ QtObject {
17
+ property int foo: 123
18
+ }
19
+ )QML";
20
+ qmlbind_component_set_data(component, data, "");
21
+ }
22
+
23
+ SECTION("with path")
24
+ {
25
+ qmlbind_component_load_path(component, "./fixtures/test.qml");
26
+ }
27
+
28
+ auto obj = qmlbind_component_create(component);
29
+ REQUIRE(qmlbind_component_get_error_string(component) == nullptr);
30
+
31
+ auto foo = qmlbind_value_get_property(obj, "foo");
32
+ REQUIRE(qmlbind_value_get_number(foo) == 123);
33
+
34
+ qmlbind_value_release(foo);
35
+ qmlbind_value_release(obj);
36
+ }
37
+
38
+ SECTION("#get_error_string")
39
+ {
40
+ auto data = R"QML(
41
+ import WRONGMODULE 1.0
42
+ QtObject {
43
+ property int foo: 123
44
+ }
45
+ )QML";
46
+ qmlbind_component_set_data(component, data, "");
47
+ auto str = qmlbind_component_get_error_string(component);
48
+
49
+ REQUIRE(str != nullptr);
50
+ REQUIRE(qmlbind_string_get_length(str) > 0);
51
+
52
+ qmlbind_string_release(str);
53
+ }
54
+
55
+ qmlbind_component_release(component);
56
+ qmlbind_engine_release(engine);
57
+ }
@@ -0,0 +1,94 @@
1
+ #include "test_helper.h"
2
+ #include <qmlbind.h>
3
+
4
+ TEST_CASE("engine")
5
+ {
6
+ auto engine = qmlbind_engine_new();
7
+
8
+ SECTION("eval")
9
+ {
10
+ SECTION("evaluates javascript")
11
+ {
12
+ auto result = qmlbind_engine_eval(engine, "1 + 2 + 3", "", 1);
13
+ REQUIRE(qmlbind_value_get_number(result) == 6);
14
+ qmlbind_value_release(result);
15
+ }
16
+ }
17
+
18
+ SECTION("get_global_object")
19
+ {
20
+ SECTION("returns global object")
21
+ {
22
+ auto global = qmlbind_engine_get_global_object(engine);
23
+ auto arrayClass = qmlbind_value_get_property(global, "Array");
24
+
25
+ REQUIRE(qmlbind_value_is_function(arrayClass));
26
+
27
+ qmlbind_value_release(arrayClass);
28
+ qmlbind_value_release(global);
29
+ }
30
+ }
31
+
32
+ SECTION("new_object")
33
+ {
34
+ SECTION("creates a new object")
35
+ {
36
+ auto object = qmlbind_engine_new_object(engine);
37
+
38
+ REQUIRE(qmlbind_value_is_object(object));
39
+ REQUIRE(!qmlbind_value_is_array(object));
40
+
41
+ qmlbind_value_release(object);
42
+ }
43
+ }
44
+
45
+ SECTION("new array")
46
+ {
47
+ SECTION("creates a new array")
48
+ {
49
+ auto array = qmlbind_engine_new_array(engine, 10);
50
+
51
+ REQUIRE(qmlbind_value_is_array(array));
52
+
53
+ auto length = qmlbind_value_get_property(array, "length");
54
+
55
+ REQUIRE(qmlbind_value_get_number(length) == 10);
56
+
57
+ qmlbind_value_release(length);
58
+ qmlbind_value_release(array);
59
+ }
60
+ }
61
+
62
+ SECTION("#add_import_path")
63
+ {
64
+ qmlbind_engine_add_import_path(engine, "./fixtures");
65
+
66
+ auto data = R"QML(
67
+ import QtQuick 2.0
68
+ import testmodule 1.0
69
+ Test {}
70
+ )QML";
71
+
72
+ auto component = qmlbind_component_new(engine);
73
+ qmlbind_component_set_data(component, data, "./fixtures/test.qml");
74
+
75
+ auto obj = qmlbind_component_create(component);
76
+ qmlbind_component_release(component);
77
+
78
+ auto foo = qmlbind_value_get_property(obj, "foo");
79
+ REQUIRE(qmlbind_value_get_number(foo) == 456);
80
+
81
+ qmlbind_value_release(foo);
82
+ qmlbind_value_release(obj);
83
+ }
84
+
85
+ qmlbind_engine_release(engine);
86
+ }
87
+
88
+ TEST_CASE("engine alives until components deleted")
89
+ {
90
+ auto engine = qmlbind_engine_new();
91
+ auto component = qmlbind_component_new(engine);
92
+ qmlbind_engine_release(engine);
93
+ qmlbind_component_release(component);
94
+ }
@@ -0,0 +1,312 @@
1
+ #include "test_helper.h"
2
+ #include <catch.hpp>
3
+ #include <qmlbind.h>
4
+ #include <QMetaObject>
5
+ #include <QMetaMethod>
6
+ #include <QByteArray>
7
+ #include <QDebug>
8
+ #include <QSharedPointer>
9
+ #include <string.h>
10
+ #include <functional>
11
+
12
+ class Test
13
+ {
14
+ public:
15
+
16
+ Test(std::function<void ()> onDestroy, qmlbind_signal_emitter emitter) :
17
+ m_value(1),
18
+ m_onDestroy(onDestroy),
19
+ m_emitter(emitter)
20
+ {
21
+ }
22
+
23
+ ~Test()
24
+ {
25
+ m_onDestroy();
26
+ }
27
+
28
+ void incrementBy(double diff)
29
+ {
30
+ setValue(value() + diff);
31
+ }
32
+
33
+ double value()
34
+ {
35
+ return m_value;
36
+ }
37
+
38
+ void setValue(double val)
39
+ {
40
+ if (m_value != val) {
41
+ m_value = val;
42
+ if (m_emitter) {
43
+ auto value = qmlbind_value_new_number(val);
44
+ qmlbind_signal_emitter_emit(m_emitter, "valueChanged", 1, &value);
45
+ qmlbind_value_release(value);
46
+ }
47
+ }
48
+ }
49
+
50
+ qmlbind_engine engine()
51
+ {
52
+ return m_engine;
53
+ }
54
+
55
+ void setEngine(qmlbind_engine engine)
56
+ {
57
+ m_engine = engine;
58
+ REQUIRE(engine == qmlbind_signal_emitter_get_engine(m_emitter));
59
+ }
60
+
61
+ private:
62
+ double m_value;
63
+ std::function<void ()> m_onDestroy;
64
+ qmlbind_engine m_engine = nullptr;
65
+ qmlbind_signal_emitter m_emitter = nullptr;
66
+ };
67
+
68
+ using TestSP = std::shared_ptr<Test>;
69
+ Q_DECLARE_METATYPE(TestSP)
70
+
71
+ namespace Handlers {
72
+
73
+ qmlbind_backref variantToBackref(const QVariant variant)
74
+ {
75
+ return reinterpret_cast<qmlbind_backref>(new QVariant(variant));
76
+ }
77
+
78
+ QVariant backrefToVariant(qmlbind_backref ref)
79
+ {
80
+ return *reinterpret_cast<QVariant *>(ref);
81
+ }
82
+
83
+ qmlbind_backref newObject(qmlbind_backref klass, qmlbind_signal_emitter emitter)
84
+ {
85
+ REQUIRE(backrefToVariant(klass).toString() == "class:Test");
86
+ auto variant = QVariant::fromValue(std::make_shared<Test>([] {}, emitter));
87
+ return variantToBackref(variant);
88
+ }
89
+
90
+ qmlbind_value invokeMethod(qmlbind_engine engine, qmlbind_backref obj, const char *method, int argc, qmlbind_value *argv)
91
+ {
92
+ auto test = backrefToVariant(obj).value<TestSP>();
93
+ REQUIRE(test);
94
+ REQUIRE(test->engine() == engine);
95
+ REQUIRE(QString(method) == "incrementBy");
96
+ REQUIRE(argc == 1);
97
+
98
+ test->incrementBy(qmlbind_value_get_number(argv[0]));
99
+ return qmlbind_value_new_number(test->value());
100
+ }
101
+
102
+ qmlbind_value invokeGetter(qmlbind_engine engine, qmlbind_backref obj, const char *property)
103
+ {
104
+ auto test = backrefToVariant(obj).value<TestSP>();
105
+ REQUIRE(test);
106
+ REQUIRE(test->engine() == engine);
107
+ REQUIRE(QString(property) == "value");
108
+
109
+ return qmlbind_value_new_number(test->value());
110
+ }
111
+
112
+ void invokeSetter(qmlbind_engine engine, qmlbind_backref obj, const char *property, qmlbind_value value)
113
+ {
114
+ auto test = backrefToVariant(obj).value<TestSP>();
115
+ REQUIRE(test);
116
+ REQUIRE(test->engine() == engine);
117
+ REQUIRE(QString(property) == "value");
118
+
119
+ test->setValue(qmlbind_value_get_number(value));
120
+ }
121
+
122
+ void deleteObject(qmlbind_backref obj)
123
+ {
124
+ delete reinterpret_cast<QVariant *>(obj);
125
+ }
126
+ }
127
+
128
+ TEST_CASE("exporter")
129
+ {
130
+ auto engine = qmlbind_engine_new();
131
+
132
+ qmlbind_interface_handlers handlers;
133
+
134
+ handlers.new_object = &Handlers::newObject;
135
+ handlers.call_method = &Handlers::invokeMethod;
136
+ handlers.set_property = &Handlers::invokeSetter;
137
+ handlers.get_property = &Handlers::invokeGetter;
138
+ handlers.delete_object = &Handlers::deleteObject;
139
+
140
+ auto interface = qmlbind_interface_new(handlers);
141
+
142
+ auto exporter = qmlbind_exporter_new(Handlers::variantToBackref("class:Test"), "Test", interface);
143
+
144
+ const char *notifierparams[] = { "value" };
145
+ auto notifierIndex = qmlbind_exporter_add_signal(exporter, "valueChanged", 1, notifierparams);
146
+ auto methodIndex = qmlbind_exporter_add_method(exporter, "incrementBy", 1);
147
+ auto propertyIndex = qmlbind_exporter_add_property(exporter, "value", "valueChanged");
148
+
149
+ auto metaobject = qmlbind_metaobject_new(exporter);
150
+ qmlbind_exporter_release(exporter);
151
+ qmlbind_interface_release(interface);
152
+
153
+ SECTION("generated metaobject")
154
+ {
155
+ auto metaobj = *reinterpret_cast<QSharedPointer<QMetaObject> *>(metaobject);
156
+
157
+ auto methodCount = metaobj->methodCount() - metaobj->methodOffset();
158
+ auto propertyCount = metaobj->propertyCount() - metaobj->propertyOffset();
159
+
160
+ REQUIRE(QByteArray(metaobj->className()) == "Test");
161
+ REQUIRE(methodCount == 2);
162
+ REQUIRE(propertyCount == 1);
163
+
164
+ SECTION("method info")
165
+ {
166
+ auto method = metaobj->method(methodIndex + metaobj->methodOffset());
167
+ REQUIRE(method.name() == "incrementBy");
168
+ REQUIRE(method.methodType() == QMetaMethod::Method);
169
+ }
170
+
171
+ SECTION("notifier signal info")
172
+ {
173
+ auto method = metaobj->method(notifierIndex + metaobj->methodOffset());
174
+ REQUIRE(method.name() == "valueChanged");
175
+ REQUIRE(method.methodType() == QMetaMethod::Signal);
176
+ REQUIRE(method.parameterNames()[0] == "value");
177
+ }
178
+
179
+ SECTION("property info")
180
+ {
181
+ auto prop = metaobj->property(propertyIndex + metaobj->propertyOffset());
182
+ REQUIRE(QByteArray(prop.name()) == "value");
183
+ }
184
+ }
185
+
186
+ SECTION("created wrapper")
187
+ {
188
+ bool destroyed = false;
189
+
190
+ {
191
+ auto test = std::make_shared<Test>([&] {
192
+ destroyed = true;
193
+ }, nullptr);
194
+
195
+ auto value = qmlbind_engine_new_wrapper(engine, metaobject, Handlers::variantToBackref(QVariant::fromValue(test)));
196
+
197
+ REQUIRE(qmlbind_value_is_wrapper(value));
198
+
199
+ test->setValue(123);
200
+
201
+ SECTION("getter")
202
+ {
203
+ auto prop = qmlbind_value_get_property(value, "value");
204
+ REQUIRE(qmlbind_value_get_number(prop) == 123);
205
+ qmlbind_value_release(prop);
206
+ }
207
+
208
+ SECTION("setter")
209
+ {
210
+ auto prop = qmlbind_value_new_number(234);
211
+ qmlbind_value_set_property(value, "value", prop);
212
+ REQUIRE(test->value() == 234);
213
+ qmlbind_value_release(prop);
214
+ }
215
+
216
+ SECTION("method")
217
+ {
218
+ auto offset = qmlbind_value_new_number(100);
219
+ auto func = qmlbind_value_get_property(value, "incrementBy");
220
+ auto result = qmlbind_value_call_with_instance(func, value, 1, &offset);
221
+
222
+ REQUIRE(test->value() == 223);
223
+
224
+ qmlbind_value_release(offset);
225
+ qmlbind_value_release(func);
226
+ qmlbind_value_release(result);
227
+ }
228
+
229
+ qmlbind_value_release(value);
230
+ }
231
+
232
+ qmlbind_engine_collect_garbage(engine);
233
+
234
+ // process deferred delete events
235
+ qmlbind_process_events();
236
+
237
+ REQUIRE(destroyed);
238
+ }
239
+
240
+ SECTION("register type")
241
+ {
242
+ auto data = R"QML(
243
+ import QtQml 2.2
244
+ import test 1.0
245
+ Test {
246
+ property bool valueChangedEmitted: false
247
+ onValueChanged: {
248
+ valueChangedEmitted = true
249
+ }
250
+ }
251
+ )QML";
252
+
253
+ qmlbind_register_type(metaobject, "test", 1, 0, "Test");
254
+
255
+ auto component = qmlbind_component_new(engine);
256
+ qmlbind_component_set_data(component, data, "");
257
+
258
+ auto error = qmlbind_component_get_error_string(component);
259
+ if (error) {
260
+ qDebug() << qmlbind_string_get_chars(error);
261
+ qmlbind_string_release(error);
262
+ }
263
+
264
+ auto obj = qmlbind_component_create(component);
265
+ auto test = Handlers::backrefToVariant(qmlbind_value_get_backref(obj)).value<TestSP>();
266
+ test->setEngine(engine);
267
+
268
+ {
269
+ auto value = qmlbind_value_get_property(obj, "value");
270
+
271
+ REQUIRE(qmlbind_value_get_number(value) == 1);
272
+
273
+ qmlbind_value_release(value);
274
+ }
275
+
276
+ {
277
+ auto emitted = qmlbind_value_get_property(obj, "valueChangedEmitted");
278
+
279
+ REQUIRE(!qmlbind_value_get_boolean(emitted));
280
+
281
+ qmlbind_value_release(emitted);
282
+ }
283
+
284
+ {
285
+ auto offset = qmlbind_value_new_number(100);
286
+ auto func = qmlbind_value_get_property(obj, "incrementBy");
287
+ auto result = qmlbind_value_call_with_instance(func, obj, 1, &offset);
288
+
289
+ REQUIRE(test != nullptr);
290
+ REQUIRE(test->value() == 101);
291
+
292
+ qmlbind_value_release(offset);
293
+ qmlbind_value_release(func);
294
+ qmlbind_value_release(result);
295
+ }
296
+
297
+ {
298
+ auto emitted = qmlbind_value_get_property(obj, "valueChangedEmitted");
299
+
300
+ REQUIRE(qmlbind_value_get_boolean(emitted));
301
+
302
+ qmlbind_value_release(emitted);
303
+ }
304
+
305
+ qmlbind_value_release(obj);
306
+
307
+ qmlbind_component_release(component);
308
+ }
309
+
310
+ qmlbind_metaobject_release(metaobject);
311
+ qmlbind_engine_release(engine);
312
+ }