qml 0.0.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,656 +0,0 @@
1
- #include "rubyvalue.h"
2
- #include "conversionerror.h"
3
- #include "util.h"
4
- #include "ext_pointer.h"
5
- #include "ext_metaobject.h"
6
- #include "objectdata.h"
7
- #include "accessobject.h"
8
- #include "listmodel.h"
9
- #include "ext_accesswrapperfactory.h"
10
- #include "kernel.h"
11
- #include <ruby/intern.h>
12
- #define ONIG_ESCAPE_UCHAR_COLLISION
13
- #include <ruby/encoding.h>
14
- #include <QVariant>
15
- #include <QDateTime>
16
- #include <QRect>
17
- #include <QSet>
18
- #include <QJSValue>
19
-
20
- #ifndef HAVE_RB_RATIONAL_NUM
21
-
22
- VALUE rb_rational_num(VALUE rat)
23
- {
24
- return RRATIONAL(rat)->num;
25
- }
26
-
27
- #endif
28
-
29
- #ifndef HAVE_RB_RATIONAL_DEN
30
-
31
- VALUE rb_rational_den(VALUE rat)
32
- {
33
- return RRATIONAL(rat)->den;
34
- }
35
-
36
- #endif
37
-
38
- namespace RubyQml {
39
-
40
- namespace detail {
41
-
42
- namespace {
43
-
44
- RubyValue convertToString(RubyValue x)
45
- {
46
- if (rb_type(x) == T_SYMBOL) {
47
- x = rb_sym_to_s(x);
48
- }
49
- return rb_convert_type(x, T_STRING, "String", "to_str");
50
- }
51
-
52
- struct ConverterHash
53
- {
54
- using FromRuby = QVariant (*)(RubyValue);
55
- using ToRuby = RubyValue (*)(const QVariant &);
56
-
57
- ConverterHash()
58
- {
59
- add<bool>();
60
-
61
- add<char>();
62
- add<short>();
63
- add<long>();
64
- add<long long>();
65
- add<unsigned char>();
66
- add<unsigned short>();
67
- add<unsigned long>();
68
- add<unsigned long long>();
69
-
70
- add<int>();
71
- add<unsigned int>();
72
-
73
- add<float>();
74
- add<double>();
75
-
76
- add<QString>();
77
- add<QByteArray>();
78
-
79
- add<QVariant>();
80
- add<QVariantList>();
81
- add<QVariantHash>();
82
- add<QVariantMap>();
83
-
84
- add<QDateTime>();
85
- add<QDate>();
86
-
87
- add<QPoint>();
88
- add<QPointF>();
89
- add<QSize>();
90
- add<QSizeF>();
91
- add<QRect>();
92
- add<QRectF>();
93
-
94
- add<QJSValue>();
95
-
96
- add<QObject *>();
97
- add<const QMetaObject *>();
98
-
99
- fromRubyHash[QMetaType::UnknownType] = [](RubyValue value) {
100
- Q_UNUSED(value);
101
- return QVariant();
102
- };
103
- toRubyHash[QMetaType::UnknownType] = [](const QVariant &variant) {
104
- Q_UNUSED(variant);
105
- return RubyValue();
106
- };
107
- }
108
-
109
- template <typename T>
110
- void add()
111
- {
112
- addFromRuby<T>();
113
- addToRuby<T>();
114
- }
115
- template <typename T>
116
- void addFromRuby()
117
- {
118
- fromRubyHash[qMetaTypeId<T>()] = [](RubyValue value) {
119
- return QVariant::fromValue(value.to<T>());
120
- };
121
- }
122
- template <typename T>
123
- void addToRuby()
124
- {
125
- toRubyHash[qMetaTypeId<T>()] = [](const QVariant &variant) {
126
- return RubyValue::from(variant.value<T>());
127
- };
128
- }
129
-
130
- QHash<int, FromRuby> fromRubyHash;
131
- QHash<int, ToRuby> toRubyHash;
132
- };
133
-
134
- Q_GLOBAL_STATIC(ConverterHash, converterHash)
135
-
136
- } // unnamed namespace
137
-
138
- RubyValue Conversion<const char *>::to(const char *str)
139
- {
140
- return rb_enc_str_new(str, strlen(str), rb_utf8_encoding());
141
- }
142
-
143
- template <> QByteArray Conversion<QByteArray>::from(RubyValue x)
144
- {
145
- x = convertToString(x);
146
- return QByteArray(RSTRING_PTR(VALUE(x)), RSTRING_LEN(VALUE(x)));
147
- }
148
-
149
- template <> RubyValue Conversion<QByteArray>::to(const QByteArray &str)
150
- {
151
- return RubyValue::from(str.constData());
152
- }
153
-
154
- template <> QString Conversion<QString>::from(RubyValue x)
155
- {
156
- x = convertToString(x);
157
- return QString::fromUtf8(RSTRING_PTR(VALUE(x)), RSTRING_LEN(VALUE(x)));
158
- }
159
-
160
- template <> RubyValue Conversion<QString>::to(const QString &str)
161
- {
162
- return RubyValue::from(str.toUtf8().constData());
163
- }
164
-
165
- template <> QDateTime Conversion<QDateTime>::from(RubyValue time)
166
- {
167
- int offset;
168
-
169
- if (time.isKindOf(rb_cTime)) {
170
- offset = time.send(RUBYQML_INTERN("gmt_offset")).to<int>();
171
- } else { // DateTime
172
- VALUE dayOffset = time.send(RUBYQML_INTERN("offset"));
173
- offset = RubyValue(rb_rational_num(dayOffset)).to<int>() * 24 * 60 * 60 / RubyValue(rb_rational_den(dayOffset)).to<int>();
174
- time = time.send(RUBYQML_INTERN("to_time"));
175
- }
176
- timeval at = rb_time_timeval(time);
177
-
178
- QDateTime dateTime;
179
- dateTime.setOffsetFromUtc(offset);
180
- dateTime.setMSecsSinceEpoch(at.tv_sec * 1000 + at.tv_usec / 1000);
181
- return dateTime;
182
- }
183
-
184
- template <> RubyValue Conversion<QDateTime>::to(const QDateTime &dateTime)
185
- {
186
- RubyValue sec = rb_rational_new(RubyValue::from(dateTime.toMSecsSinceEpoch()), RubyValue::from(1000));
187
- RubyValue time = rb_time_num_new(sec, RubyValue::from(dateTime.offsetFromUtc()));
188
- return time.send(RUBYQML_INTERN("to_datetime"));
189
- }
190
-
191
- template <> QDate Conversion<QDate>::from(RubyValue x)
192
- {
193
- int y = x.send(RUBYQML_INTERN("year")).to<int>();
194
- int m = x.send(RUBYQML_INTERN("month")).to<int>();
195
- int d = x.send(RUBYQML_INTERN("day")).to<int>();
196
- return QDate(y, m, d);
197
- }
198
-
199
- template <> RubyValue Conversion<QDate>::to(const QDate &date)
200
- {
201
- static auto klass = RubyClass::fromPath("Date");
202
- return klass.toValue().send(RUBYQML_INTERN("new"), RubyValue::from(date.year()), RubyValue::from(date.month()), RubyValue::from(date.day()));
203
- }
204
-
205
- template <> QPoint Conversion<QPoint>::from(RubyValue value)
206
- {
207
- auto x = value.send(RUBYQML_INTERN("x")).to<int>();
208
- auto y = value.send(RUBYQML_INTERN("y")).to<int>();
209
- return QPoint(x, y);
210
- }
211
-
212
- template <> RubyValue Conversion<QPoint>::to(const QPoint &point)
213
- {
214
- static auto klass = RubyClass::fromPath("QML::Geometry::Point");
215
- return klass.toValue().send(RUBYQML_INTERN("new"), RubyValue::from(point.x()), RubyValue::from(point.y()));
216
- }
217
-
218
- template <> QPointF Conversion<QPointF>::from(RubyValue value)
219
- {
220
- auto x = value.send(RUBYQML_INTERN("x")).to<double>();
221
- auto y = value.send(RUBYQML_INTERN("y")).to<double>();
222
- return QPointF(x, y);
223
- }
224
-
225
- template <> RubyValue Conversion<QPointF>::to(const QPointF &point)
226
- {
227
- static auto klass = RubyClass::fromPath("QML::Geometry::Point");
228
- return klass.toValue().send(RUBYQML_INTERN("new"), RubyValue::from(point.x()), RubyValue::from(point.y()));
229
- }
230
-
231
- template <> QSize Conversion<QSize>::from(RubyValue value)
232
- {
233
- auto width = value.send(RUBYQML_INTERN("width")).to<int>();
234
- auto height= value.send(RUBYQML_INTERN("height")).to<int>();
235
- return QSize(width, height);
236
- }
237
-
238
- template <> RubyValue Conversion<QSize>::to(const QSize &size)
239
- {
240
- static auto klass = RubyClass::fromPath("QML::Geometry::Size");
241
- return klass.toValue().send(RUBYQML_INTERN("new"), RubyValue::from(size.width()), RubyValue::from(size.height()));
242
- }
243
-
244
- template <> QSizeF Conversion<QSizeF>::from(RubyValue value)
245
- {
246
- auto width = value.send(RUBYQML_INTERN("width")).to<double>();
247
- auto height = value.send(RUBYQML_INTERN("height")).to<double>();
248
- return QSizeF(width, height);
249
- }
250
-
251
- template <> RubyValue Conversion<QSizeF>::to(const QSizeF &size)
252
- {
253
- static auto klass = RubyClass::fromPath("QML::Geometry::Size");
254
- return klass.toValue().send(RUBYQML_INTERN("new"), RubyValue::from(size.width()), RubyValue::from(size.height()));
255
- }
256
-
257
- template <> QRect Conversion<QRect>::from(RubyValue value)
258
- {
259
- auto x = value.send(RUBYQML_INTERN("x")).to<int>();
260
- auto y = value.send(RUBYQML_INTERN("y")).to<int>();
261
- auto w = value.send(RUBYQML_INTERN("width")).to<int>();
262
- auto h = value.send(RUBYQML_INTERN("height")).to<int>();
263
- return QRect(QPoint(x, y), QSize(w, h));
264
- }
265
-
266
- template <> RubyValue Conversion<QRect>::to(const QRect &rect)
267
- {
268
- static auto klass = RubyClass::fromPath("QML::Geometry::Rectangle");
269
- return klass.toValue().send(RUBYQML_INTERN("new"),
270
- RubyValue::from(rect.x()), RubyValue::from(rect.y()),
271
- RubyValue::from(rect.width()), RubyValue::from(rect.height()));
272
- }
273
-
274
- template <> QRectF Conversion<QRectF>::from(RubyValue value)
275
- {
276
- auto x = value.send(RUBYQML_INTERN("x")).to<double>();
277
- auto y = value.send(RUBYQML_INTERN("y")).to<double>();
278
- auto w = value.send(RUBYQML_INTERN("width")).to<double>();
279
- auto h = value.send(RUBYQML_INTERN("height")).to<double>();
280
- return QRectF(QPointF(x, y), QSizeF(w, h));
281
- }
282
-
283
- template <> RubyValue Conversion<QRectF>::to(const QRectF &rect)
284
- {
285
- static auto klass = RubyClass::fromPath("QML::Geometry::Rectangle");
286
- return klass.toValue().send(RUBYQML_INTERN("new"),
287
- RubyValue::from(rect.x()), RubyValue::from(rect.y()),
288
- RubyValue::from(rect.width()), RubyValue::from(rect.height()));
289
- }
290
-
291
- template <> QVariant Conversion<QVariant>::from(RubyValue x)
292
- {
293
- return x.toVariant();
294
- }
295
-
296
- template <> RubyValue Conversion<QVariant>::to(const QVariant &variant)
297
- {
298
- return RubyValue::fromVariant(variant);
299
- }
300
-
301
- template <> const QMetaObject *Conversion<const QMetaObject *>::from(RubyValue x)
302
- {
303
- if (x == RubyValue()) {
304
- return nullptr;
305
- }
306
- return wrapperRubyClass<Ext_MetaObject>().unwrap(x)->metaObject();
307
- }
308
-
309
- template <> RubyValue Conversion<const QMetaObject *>::to(const QMetaObject *metaobj)
310
- {
311
- if (!metaobj) {
312
- return Qnil;
313
- }
314
- return Ext_MetaObject::fromMetaObject(metaobj);
315
- }
316
-
317
- template <> QJSValue Conversion<QJSValue>::from(RubyValue x)
318
- {
319
- return Kernel::instance()->engine()->toScriptValue(x.to<QVariant>());
320
- }
321
-
322
- template <> RubyValue Conversion<QJSValue>::to(const QJSValue &jsValue)
323
- {
324
- return RubyValue::from(jsValue.toVariant());
325
- }
326
-
327
- } // namespace detail
328
-
329
- Q_GLOBAL_STATIC(QSet<int>, enumeratorMetaTypes)
330
-
331
- bool RubyValue::isConvertibleTo(int metaType) const
332
- {
333
- auto x = *this;
334
- if (metaType == QMetaType::QVariant) {
335
- return true;
336
- }
337
- switch (rb_type(x)) {
338
- case T_NIL:
339
- return metaType == QMetaType::QObjectStar || metaType == QMetaType::type("const QMetaObject*");
340
- case T_TRUE:
341
- case T_FALSE:
342
- return metaType == QMetaType::Bool;
343
- case T_FIXNUM:
344
- case T_BIGNUM:
345
- switch (metaType) {
346
- case QMetaType::Char:
347
- case QMetaType::Short:
348
- case QMetaType::Long:
349
- case QMetaType::LongLong:
350
-
351
- case QMetaType::UChar:
352
- case QMetaType::UShort:
353
- case QMetaType::ULong:
354
- case QMetaType::ULongLong:
355
-
356
- case QMetaType::Int:
357
- case QMetaType::UInt:
358
-
359
- case QMetaType::Float:
360
- case QMetaType::Double:
361
- return true;
362
- default:
363
- if (enumeratorMetaTypes->contains(metaType)) {
364
- return true;
365
- }
366
- return false;
367
- }
368
- case T_FLOAT:
369
- switch (metaType) {
370
- case QMetaType::Float:
371
- case QMetaType::Double:
372
- return true;
373
- default:
374
- return false;
375
- }
376
- case T_SYMBOL:
377
- case T_STRING:
378
- switch (metaType) {
379
- case QMetaType::QByteArray:
380
- case QMetaType::QString:
381
- return true;
382
- default:
383
- return false;
384
- }
385
- case T_ARRAY:
386
- switch (metaType) {
387
- case QMetaType::QVariantList:
388
- return true;
389
- default:
390
- return false;
391
- }
392
- case T_HASH:
393
- switch (metaType) {
394
- case QMetaType::QVariantHash:
395
- case QMetaType::QVariantMap:
396
- return true;
397
- default:
398
- return false;
399
- }
400
- default:
401
-
402
- break;
403
- }
404
-
405
- if (rb_obj_is_kind_of(x, rb_cTime)) {
406
- return metaType == QMetaType::QDateTime;
407
- }
408
- static auto dateTimeClass = RubyClass::fromPath("DateTime");
409
- if (rb_obj_is_kind_of(x, dateTimeClass)) {
410
- return metaType == QMetaType::QDateTime;
411
- }
412
- static auto dateClass = RubyClass::fromPath("Date");
413
- if (rb_obj_is_kind_of(x, dateClass)) {
414
- return metaType == QMetaType::QDate || metaType == QMetaType::QDateTime;
415
- }
416
- static auto objectBaseClass = RubyClass::fromPath("QML::QtObjectBase");
417
- if (rb_obj_is_kind_of(x, objectBaseClass)) {
418
- if (metaType == QMetaType::QObjectStar) {
419
- return true;
420
- }
421
- if (QMetaType::metaObjectForType(metaType)) {
422
- auto metaObj = QMetaType::metaObjectForType(metaType);
423
- if (x.to<QObject *>()->inherits(metaObj->className())) {
424
- return true;
425
- }
426
- }
427
- return false;
428
- }
429
- if (rb_obj_is_kind_of(x, wrapperRubyClass<Ext_MetaObject>())) {
430
- return metaType == QMetaType::type("const QMetaObject*");
431
- }
432
- auto accessModule = RubyModule::fromPath("QML::Access");
433
- if (rb_obj_is_kind_of(x, accessModule)) {
434
- return metaType == QMetaType::QObjectStar;
435
- }
436
-
437
- static auto pointClass = RubyModule::fromPath("QML::Geometry::Point");
438
- if (rb_obj_is_kind_of(x, pointClass)) {
439
- return metaType == QMetaType::QPoint || metaType == QMetaType::QPointF;
440
- }
441
- static auto sizeClass = RubyModule::fromPath("QML::Geometry::Size");
442
- if (rb_obj_is_kind_of(x, sizeClass)) {
443
- return metaType == QMetaType::QSize || metaType == QMetaType::QSizeF;
444
- }
445
- static auto rectClass = RubyModule::fromPath("QML::Geometry::Rectangle");
446
- if (rb_obj_is_kind_of(x, rectClass)) {
447
- return metaType == QMetaType::QRect || metaType == QMetaType::QRectF;
448
- }
449
- static auto listModelClass = RubyModule::fromPath("QML::Data::ListModel");
450
-
451
- if (rb_obj_is_kind_of(x, listModelClass)) {
452
- return metaType == QMetaType::QObjectStar;
453
- }
454
- return false;
455
- }
456
-
457
- int RubyValue::defaultMetaType() const
458
- {
459
- auto x = *this;
460
- switch (rb_type(x)) {
461
- case T_NIL:
462
- return QMetaType::UnknownType;
463
- case T_TRUE:
464
- case T_FALSE:
465
- return QMetaType::Bool;
466
- case T_FIXNUM:
467
- case T_BIGNUM:
468
- return QMetaType::Int;
469
- case T_FLOAT:
470
- return QMetaType::Double;
471
- case T_SYMBOL:
472
- return QMetaType::QString;
473
- case T_STRING:
474
- if (rb_enc_get_index(x) == rb_ascii8bit_encindex()) {
475
- return QMetaType::QByteArray;
476
- } else {
477
- return QMetaType::QString;
478
- }
479
- case T_ARRAY:
480
- return QMetaType::QVariantList;
481
- case T_HASH:
482
- return QMetaType::QVariantHash;
483
- default:
484
- break;
485
- }
486
- if (rb_obj_is_kind_of(x, rb_cTime)) {
487
- return QMetaType::QDateTime;
488
- }
489
- static auto dateTimeClass = RubyModule::fromPath("DateTime");
490
- if (rb_obj_is_kind_of(x, dateTimeClass)) {
491
- return QMetaType::QDateTime;
492
- }
493
- static auto dateClass = RubyModule::fromPath("Date");
494
- if (rb_obj_is_kind_of(x, dateClass)) {
495
- return QMetaType::QDate;
496
- }
497
-
498
- static auto objectBaseClass = RubyClass::fromPath("QML::QtObjectBase");
499
- if (rb_obj_is_kind_of(x, objectBaseClass)) {
500
- return QMetaType::QObjectStar;
501
- }
502
- if (rb_obj_is_kind_of(x, wrapperRubyClass<Ext_MetaObject>())) {
503
- return QMetaType::type("const QMetaObject*");
504
- }
505
- auto accessModule = RubyModule::fromPath("QML::Access");
506
- if (rb_obj_is_kind_of(x, accessModule)) {
507
- return QMetaType::QObjectStar;
508
- }
509
-
510
- static auto pointClass = RubyModule::fromPath("QML::Geometry::Point");
511
- if (rb_obj_is_kind_of(x, pointClass)) {
512
- return QMetaType::QPointF;
513
- }
514
- static auto sizeClass = RubyModule::fromPath("QML::Geometry::Size");
515
- if (rb_obj_is_kind_of(x, sizeClass)) {
516
- return QMetaType::QSizeF;
517
- }
518
- static auto rectClass = RubyModule::fromPath("QML::Geometry::Rectangle");
519
- if (rb_obj_is_kind_of(x, rectClass)) {
520
- return QMetaType::QRectF;
521
- }
522
-
523
- static auto listModelClass = RubyModule::fromPath("QML::Data::ListModel");
524
- if (rb_obj_is_kind_of(x, listModelClass)) {
525
- return QMetaType::QObjectStar;
526
- }
527
- return QMetaType::UnknownType;
528
- }
529
-
530
- RubyValue RubyValue::fromVariant(const QVariant &variant)
531
- {
532
- auto &hash = detail::converterHash->toRubyHash;
533
- auto type = variant.userType();
534
- if (QMetaType::metaObjectForType(type)) {
535
- type = QMetaType::QObjectStar;
536
- }
537
- if (enumeratorMetaTypes->contains(type)) {
538
- auto intValue = *static_cast<const int *>(variant.data());
539
- return from(intValue);
540
- }
541
- if (!hash.contains(type)) {
542
- throw ConversionError(QString("failed to convert QVariant value (%1)")
543
- .arg(QMetaType::typeName(type)));
544
- }
545
- return hash[type](variant);
546
- }
547
-
548
- QVariant RubyValue::toVariant() const
549
- {
550
- return toVariant(defaultMetaType());
551
- }
552
-
553
- QVariant RubyValue::toVariant(int type) const
554
- {
555
- auto x = *this;
556
- auto &hash = detail::converterHash->fromRubyHash;
557
- if (!hash.contains(type)) {
558
- auto metaobj = QMetaType::metaObjectForType(type);
559
- if (metaobj) {
560
- auto qobj = hash[QMetaType::QObjectStar](x).value<QObject *>();
561
- if (qobj->inherits(metaobj->className())) {
562
- return QVariant::fromValue(qobj);
563
- }
564
- throw ConversionError(QString("failed to convert QObject value (%1 to %2)")
565
- .arg(qobj->metaObject()->className())
566
- .arg(metaobj->className()));
567
- }
568
- if (enumeratorMetaTypes->contains(type)) {
569
- auto intValue = to<int>();
570
- auto data = QMetaType::create(type);
571
- *static_cast<int *>(data) = intValue;
572
- return QVariant(type, data);
573
- }
574
- throw ConversionError(QString("failed to convert Ruby value (%1 to %2)")
575
- .arg(rb_obj_classname(x))
576
- .arg(QMetaType::typeName(type)));
577
- return QVariant();
578
- }
579
- return hash[type](x);
580
- }
581
-
582
- RubyValue RubyValue::fromQObject(QObject *obj, bool implicit)
583
- {
584
- if (!obj) {
585
- return Qnil;
586
- }
587
-
588
- if (implicit) {
589
- auto accessObj = dynamic_cast<AccessWrapper *>(obj);
590
- if (accessObj) {
591
- return accessObj->wrappedValue();
592
- }
593
- auto listModel = dynamic_cast<ListModel *>(obj);
594
- if (listModel) {
595
- return listModel->rubyModel();
596
- }
597
- }
598
-
599
- auto data = ObjectData::getOrCreate(obj);
600
- if (data->rubyObject) {
601
- return data->rubyObject;
602
- }
603
-
604
- auto metaobj = Ext_MetaObject::fromMetaObject(obj->metaObject());
605
- auto pointer = Ext_Pointer::fromQObject(obj, false);
606
-
607
- RubyValue wrapper;
608
-
609
- auto klass = rb_funcall(metaobj, RUBYQML_INTERN("build_class"), 0);
610
- wrapper = rb_obj_alloc(klass);
611
- rb_funcall(wrapper, RUBYQML_INTERN("pointer="), 1, pointer);
612
- rb_obj_call_init(wrapper, 0, nullptr);
613
-
614
- data->rubyObject = wrapper;
615
- return wrapper;
616
- }
617
-
618
- QObject *RubyValue::toQObject() const
619
- {
620
- auto x = *this;
621
-
622
- if (x == RubyValue()) {
623
- return nullptr;
624
- }
625
- static auto accessModule = RubyModule::fromPath("QML::Access");
626
- if (x.isKindOf(accessModule)) {
627
- auto wrapperFactory = rb_funcall(rb_obj_class(x), RUBYQML_INTERN("access_wrapper_factory"), 0);
628
- return wrapperRubyClass<Ext_AccessWrapperFactory>().unwrap(wrapperFactory)->create(x);
629
- }
630
- static auto listModelClass = RubyModule::fromPath("QML::Data::ListModel");
631
- if (x.isKindOf(listModelClass)) {
632
- return new ListModel(x);
633
- }
634
-
635
- static auto objectBaseClass = RubyClass::fromPath("QML::QtObjectBase");
636
- if (!x.isKindOf(objectBaseClass)) {
637
- throw ConversionError(QString("expected QML::QtObjectbase, got %1")
638
- .arg(x.send("class").send("name").to<QString>()));
639
- }
640
- auto objptr = x.send(RUBYQML_INTERN("pointer"));
641
- auto obj = wrapperRubyClass<Ext_Pointer>().unwrap(objptr)->fetchQObject();
642
- Ext_MetaObject::fromMetaObject(obj->metaObject()).send(RUBYQML_INTERN("build_class"));
643
- return obj;
644
- }
645
-
646
- ID RubyValue::toID() const
647
- {
648
- return SYM2ID(rb_convert_type(*this, T_SYMBOL, "Symbol", "to_sym"));
649
- }
650
-
651
- void RubyValue::addEnumeratorMetaType(int metaType)
652
- {
653
- *enumeratorMetaTypes << metaType;
654
- }
655
-
656
- } // namespace RubyQml