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
@@ -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