qml 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +46 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +15 -0
  5. data/.yardopts +4 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +351 -0
  9. data/Rakefile +6 -0
  10. data/examples/assets/fonts/fontawesome-webfont.ttf +0 -0
  11. data/examples/fizzbuzz/fizzbuzz.rb +43 -0
  12. data/examples/fizzbuzz/main.qml +38 -0
  13. data/examples/imageprovider/imageprovider.rb +57 -0
  14. data/examples/imageprovider/main.qml +51 -0
  15. data/examples/todo/main.qml +70 -0
  16. data/examples/todo/todo.rb +36 -0
  17. data/examples/twitter/main.qml +36 -0
  18. data/examples/twitter/twitter.rb +55 -0
  19. data/ext/qml/accessclass.cpp +71 -0
  20. data/ext/qml/accessclass.h +19 -0
  21. data/ext/qml/accessobject.cpp +30 -0
  22. data/ext/qml/accessobject.h +22 -0
  23. data/ext/qml/application.cpp +54 -0
  24. data/ext/qml/application.h +17 -0
  25. data/ext/qml/common.h +18 -0
  26. data/ext/qml/ext_accesssupport.cpp +77 -0
  27. data/ext/qml/ext_accesssupport.h +42 -0
  28. data/ext/qml/ext_gcmarker.cpp +39 -0
  29. data/ext/qml/ext_gcmarker.h +27 -0
  30. data/ext/qml/ext_kernel.cpp +62 -0
  31. data/ext/qml/ext_kernel.h +11 -0
  32. data/ext/qml/ext_metaobject.cpp +410 -0
  33. data/ext/qml/ext_metaobject.h +62 -0
  34. data/ext/qml/ext_pluginloader.cpp +55 -0
  35. data/ext/qml/ext_pluginloader.h +32 -0
  36. data/ext/qml/ext_pointer.cpp +134 -0
  37. data/ext/qml/ext_pointer.h +43 -0
  38. data/ext/qml/ext_testutil.cpp +42 -0
  39. data/ext/qml/ext_testutil.h +11 -0
  40. data/ext/qml/extconf.rb +84 -0
  41. data/ext/qml/foreignclass.cpp +72 -0
  42. data/ext/qml/foreignclass.h +88 -0
  43. data/ext/qml/foreignmetaobject.cpp +345 -0
  44. data/ext/qml/foreignmetaobject.h +46 -0
  45. data/ext/qml/foreignobject.cpp +22 -0
  46. data/ext/qml/foreignobject.h +21 -0
  47. data/ext/qml/functioninfo.h +16 -0
  48. data/ext/qml/init.cpp +69 -0
  49. data/ext/qml/listmodel.cpp +112 -0
  50. data/ext/qml/listmodel.h +43 -0
  51. data/ext/qml/markable.h +12 -0
  52. data/ext/qml/objectdata.cpp +26 -0
  53. data/ext/qml/objectdata.h +20 -0
  54. data/ext/qml/objectgc.cpp +69 -0
  55. data/ext/qml/objectgc.h +28 -0
  56. data/ext/qml/plugins/core/applicationextension.cpp +34 -0
  57. data/ext/qml/plugins/core/applicationextension.h +28 -0
  58. data/ext/qml/plugins/core/componentextension.cpp +41 -0
  59. data/ext/qml/plugins/core/componentextension.h +28 -0
  60. data/ext/qml/plugins/core/contextextension.cpp +39 -0
  61. data/ext/qml/plugins/core/contextextension.h +29 -0
  62. data/ext/qml/plugins/core/core.pro +29 -0
  63. data/ext/qml/plugins/core/coreplugin.cpp +87 -0
  64. data/ext/qml/plugins/core/coreplugin.h +49 -0
  65. data/ext/qml/plugins/core/engineextension.cpp +27 -0
  66. data/ext/qml/plugins/core/engineextension.h +28 -0
  67. data/ext/qml/plugins/core/imageprovider.cpp +38 -0
  68. data/ext/qml/plugins/core/imageprovider.h +18 -0
  69. data/ext/qml/plugins/core/imagerequestpromise.cpp +19 -0
  70. data/ext/qml/plugins/core/imagerequestpromise.h +21 -0
  71. data/ext/qml/plugins/core/qmlexception.cpp +11 -0
  72. data/ext/qml/plugins/core/qmlexception.h +17 -0
  73. data/ext/qml/plugins/testutil/objectlifechecker.cpp +17 -0
  74. data/ext/qml/plugins/testutil/objectlifechecker.h +24 -0
  75. data/ext/qml/plugins/testutil/ownershiptest.cpp +26 -0
  76. data/ext/qml/plugins/testutil/ownershiptest.h +30 -0
  77. data/ext/qml/plugins/testutil/testobject.cpp +6 -0
  78. data/ext/qml/plugins/testutil/testobject.h +108 -0
  79. data/ext/qml/plugins/testutil/testobjectsubclass.cpp +10 -0
  80. data/ext/qml/plugins/testutil/testobjectsubclass.h +19 -0
  81. data/ext/qml/plugins/testutil/testutil.pro +20 -0
  82. data/ext/qml/plugins/testutil/testutilplugin.cpp +47 -0
  83. data/ext/qml/plugins/testutil/testutilplugin.h +32 -0
  84. data/ext/qml/qmltyperegisterer.cpp +74 -0
  85. data/ext/qml/qmltyperegisterer.h +30 -0
  86. data/ext/qml/rubyclass.cpp +94 -0
  87. data/ext/qml/rubyclass.h +234 -0
  88. data/ext/qml/rubyvalue.cpp +690 -0
  89. data/ext/qml/rubyvalue.h +256 -0
  90. data/ext/qml/signalforwarder.cpp +66 -0
  91. data/ext/qml/signalforwarder.h +29 -0
  92. data/ext/qml/util.cpp +120 -0
  93. data/ext/qml/util.h +101 -0
  94. data/ext/qml/valuereference.cpp +50 -0
  95. data/ext/qml/valuereference.h +22 -0
  96. data/ext/qml/weakvaluereference.cpp +27 -0
  97. data/ext/qml/weakvaluereference.h +19 -0
  98. data/lib/qml.rb +41 -0
  99. data/lib/qml/access.rb +137 -0
  100. data/lib/qml/application.rb +139 -0
  101. data/lib/qml/class_builder.rb +126 -0
  102. data/lib/qml/component.rb +53 -0
  103. data/lib/qml/context.rb +71 -0
  104. data/lib/qml/data.rb +2 -0
  105. data/lib/qml/data/array_model.rb +103 -0
  106. data/lib/qml/data/error.rb +5 -0
  107. data/lib/qml/data/list_model.rb +146 -0
  108. data/lib/qml/dispatchable.rb +34 -0
  109. data/lib/qml/dispatcher.rb +61 -0
  110. data/lib/qml/engine.rb +54 -0
  111. data/lib/qml/error_converter.rb +15 -0
  112. data/lib/qml/errors.rb +26 -0
  113. data/lib/qml/geometry.rb +3 -0
  114. data/lib/qml/geometry/point.rb +5 -0
  115. data/lib/qml/geometry/rectangle.rb +5 -0
  116. data/lib/qml/geometry/size.rb +5 -0
  117. data/lib/qml/image_provider.rb +87 -0
  118. data/lib/qml/meta_object.rb +20 -0
  119. data/lib/qml/models.rb +1 -0
  120. data/lib/qml/name_helper.rb +12 -0
  121. data/lib/qml/platform.rb +15 -0
  122. data/lib/qml/plugin_loader.rb +46 -0
  123. data/lib/qml/plugins.rb +26 -0
  124. data/lib/qml/qml.rb +1 -0
  125. data/lib/qml/qt.rb +6 -0
  126. data/lib/qml/qt_classes.rb +9 -0
  127. data/lib/qml/qt_object_base.rb +108 -0
  128. data/lib/qml/reactive.rb +8 -0
  129. data/lib/qml/reactive/bindable.rb +79 -0
  130. data/lib/qml/reactive/chained_signal.rb +25 -0
  131. data/lib/qml/reactive/error.rb +5 -0
  132. data/lib/qml/reactive/object.rb +278 -0
  133. data/lib/qml/reactive/property.rb +19 -0
  134. data/lib/qml/reactive/signal.rb +116 -0
  135. data/lib/qml/reactive/signal_spy.rb +27 -0
  136. data/lib/qml/reactive/signals/map_signal.rb +21 -0
  137. data/lib/qml/reactive/signals/merge_signal.rb +21 -0
  138. data/lib/qml/reactive/signals/select_signal.rb +21 -0
  139. data/lib/qml/reactive/simple_property.rb +17 -0
  140. data/lib/qml/reactive/unbound_property.rb +42 -0
  141. data/lib/qml/reactive/unbound_signal.rb +51 -0
  142. data/lib/qml/root_path.rb +3 -0
  143. data/lib/qml/test_util.rb +1 -0
  144. data/lib/qml/test_util/object_life_checker.rb +17 -0
  145. data/lib/qml/version.rb +3 -0
  146. data/lib/qml/wrappable.rb +9 -0
  147. data/qml.gemspec +28 -0
  148. data/spec/assets/testobj.qml +5 -0
  149. data/spec/qml/.access_spec.rb.swp +0 -0
  150. data/spec/qml/access_spec.rb +162 -0
  151. data/spec/qml/application_spec.rb +43 -0
  152. data/spec/qml/component_spec.rb +44 -0
  153. data/spec/qml/context_spec.rb +43 -0
  154. data/spec/qml/conversion_spec.rb +59 -0
  155. data/spec/qml/data/array_model_spec.rb +215 -0
  156. data/spec/qml/dispatchable_spec.rb +26 -0
  157. data/spec/qml/dispatcher_spec.rb +48 -0
  158. data/spec/qml/geometry/point_spec.rb +4 -0
  159. data/spec/qml/geometry/rectangle_spec.rb +4 -0
  160. data/spec/qml/geometry/size_spec.rb +4 -0
  161. data/spec/qml/plugin_loader_spec.rb +33 -0
  162. data/spec/qml/qt_object_base_spec.rb +119 -0
  163. data/spec/qml/reactive/object_spec.rb +273 -0
  164. data/spec/qml/reactive/property_spec.rb +70 -0
  165. data/spec/qml/reactive/signal_spec.rb +191 -0
  166. data/spec/qml/reactive/signal_spy_spec.rb +26 -0
  167. data/spec/qml/test_object_spec.rb +186 -0
  168. data/spec/qml_spec.rb +7 -0
  169. data/spec/spec_helper.rb +5 -0
  170. metadata +321 -0
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,43 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__)
2
+ require 'qml'
3
+ require 'pathname'
4
+
5
+ module Examples
6
+ module FizzBuzz
7
+ VERSION = '0.1'
8
+
9
+ class FizzBuzz
10
+ include QML::Access
11
+
12
+ property :input, '0'
13
+ property :result , ''
14
+ signal :inputWasFizzBuzz, []
15
+
16
+ on_changed :input do
17
+ i = input.to_i
18
+ self.result = case
19
+ when i % 15 == 0
20
+ inputWasFizzBuzz.emit
21
+ "FizzBuzz"
22
+ when i % 3 == 0
23
+ "Fizz"
24
+ when i % 5 == 0
25
+ "Buzz"
26
+ else
27
+ i.to_s
28
+ end
29
+ end
30
+
31
+ def quit
32
+ puts "quitting..."
33
+ QML.application.quit
34
+ end
35
+
36
+ register_to_qml
37
+ end
38
+ end
39
+ end
40
+
41
+ QML.application do |app|
42
+ app.load_path Pathname(__FILE__) + '../main.qml'
43
+ end
@@ -0,0 +1,38 @@
1
+ import QtQuick 2.2
2
+ import QtQuick.Controls 1.1
3
+ import QtQuick.Layouts 1.1
4
+ import Examples.FizzBuzz 0.1
5
+
6
+ ApplicationWindow {
7
+ visible: true
8
+ width: 200
9
+ height: 200
10
+ title: "FizzBuzz"
11
+
12
+ ColumnLayout {
13
+ anchors.fill: parent
14
+ anchors.margins: 10
15
+ TextField {
16
+ placeholderText: "Input"
17
+ text: "0"
18
+ id: textField
19
+ }
20
+ Text {
21
+ y: 100
22
+ id: text
23
+ text: fizzBuzz.result
24
+ }
25
+ Button {
26
+ text: 'Quit'
27
+ onClicked: fizzBuzz.quit()
28
+ }
29
+ Text {
30
+ id: lastFizzBuzz
31
+ }
32
+ }
33
+ FizzBuzz {
34
+ id: fizzBuzz
35
+ input: textField.text
36
+ onInputWasFizzBuzz: lastFizzBuzz.text = "Last FizzBuzz: " + textField.text
37
+ }
38
+ }
@@ -0,0 +1,57 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__)
2
+ require 'qml'
3
+ require 'open-uri'
4
+ require 'singleton'
5
+ require 'celluloid'
6
+
7
+ module Examples
8
+ module ImageProvider
9
+
10
+ VERSION = '0.1.0'
11
+
12
+ class ImageFetcher
13
+ include Celluloid
14
+ include Singleton
15
+
16
+ def set_url(url)
17
+ @url = url
18
+ end
19
+
20
+ def fetch(request)
21
+ image =
22
+ case request.id
23
+ when "image"
24
+ open(@url, 'rb') { |f| f.read } rescue nil
25
+ end
26
+ request.finish(image || "")
27
+ end
28
+ end
29
+
30
+ class Controller
31
+ include QML::Access
32
+
33
+ property :url, ''
34
+
35
+ on_changed :url do
36
+ ImageFetcher.instance.async.set_url url
37
+ end
38
+
39
+ register_to_qml
40
+ end
41
+
42
+ class Provider < QML::ImageProvider
43
+
44
+ def request(req)
45
+ case req.id
46
+ when 'image'
47
+ ImageFetcher.instance.fetch(req)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ QML.application do |app|
55
+ app.engine.add_image_provider 'example', Examples::ImageProvider::Provider.new
56
+ app.load_path Pathname(__FILE__) + '../main.qml'
57
+ end
@@ -0,0 +1,51 @@
1
+ import QtQuick 2.2
2
+ import QtQuick.Controls 1.1
3
+ import QtQuick.Layouts 1.1
4
+ import Examples.ImageProvider 0.1
5
+
6
+ ApplicationWindow {
7
+ visible: true
8
+ width: 200
9
+ height: 200
10
+
11
+ GridLayout {
12
+ anchors.fill: parent
13
+ anchors.margins: 10
14
+ columns: 1
15
+
16
+ Image {
17
+ id: image
18
+ source: 'image://example/image'
19
+ asynchronous: true
20
+ cache: false
21
+ fillMode: Image.Pad
22
+ Layout.fillHeight: true
23
+
24
+ function reload() {
25
+ source = ''
26
+ source = 'image://example/image'
27
+ }
28
+ }
29
+
30
+ GridLayout {
31
+ columns: 2
32
+
33
+ Label {
34
+ text: 'Image URL'
35
+ }
36
+
37
+ TextField {
38
+ id: textField
39
+ Layout.fillWidth: true
40
+ onEditingFinished: {
41
+ image.reload()
42
+ }
43
+ }
44
+ }
45
+ }
46
+
47
+ Controller {
48
+ id: provider
49
+ url: textField.text
50
+ }
51
+ }
@@ -0,0 +1,70 @@
1
+ import QtQuick 2.3
2
+ import QtQuick.Controls 1.2
3
+ import QtQuick.Layouts 1.1
4
+ import Examples.Todo 0.1
5
+
6
+ ApplicationWindow {
7
+ visible: true
8
+ title: "Todo Array Model"
9
+
10
+ FontLoader {
11
+ source: "../assets/fonts/fontawesome-webfont.ttf"
12
+ }
13
+ width: layout.implicitWidth
14
+ height: layout.implicitHeight
15
+
16
+ RowLayout {
17
+ id: layout
18
+ anchors.fill: parent
19
+ anchors.margins: 10
20
+ ColumnLayout {
21
+ TextField {
22
+ placeholderText: "Title"
23
+ id: titleField
24
+ }
25
+ TextField {
26
+ placeholderText: "Description"
27
+ id: descriptionField
28
+ }
29
+ Calendar {
30
+ id: calendar
31
+ }
32
+ Button {
33
+ text: "Add"
34
+ onClicked: todo.add()
35
+ }
36
+ }
37
+ ListView {
38
+ model: todo.model
39
+ spacing: 10
40
+ Layout.fillWidth: true
41
+ Layout.fillHeight: true
42
+ Layout.alignment: Qt.AlignTop
43
+ Layout.minimumWidth: 300
44
+ delegate: ColumnLayout {
45
+ Text {
46
+ font.bold: true
47
+ text: title
48
+ }
49
+ Text {
50
+ text: description
51
+ }
52
+ RowLayout {
53
+ Text {
54
+ font.family: "FontAwesome"
55
+ text: "\uf073"
56
+ }
57
+ Text {
58
+ text: due_date
59
+ }
60
+ }
61
+ }
62
+ }
63
+ }
64
+ TodoController {
65
+ id: todo
66
+ title: titleField.text
67
+ description: descriptionField.text
68
+ due_date: calendar.selectedDate
69
+ }
70
+ }
@@ -0,0 +1,36 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__)
2
+ require 'qml'
3
+ require 'pathname'
4
+
5
+ module Examples
6
+ module Todo
7
+ VERSION = '0.1'
8
+
9
+ class TodoModel < QML::Data::ArrayModel
10
+ column :title, :description, :due_date
11
+ end
12
+
13
+ class TodoController
14
+ include QML::Access
15
+ register_to_qml
16
+
17
+ property :title, ''
18
+ property :description, ''
19
+ property :due_date, ''
20
+ property :model, TodoModel.new
21
+
22
+ def add
23
+ item = OpenStruct.new(
24
+ title: title,
25
+ description: description,
26
+ due_date: due_date)
27
+ p item
28
+ model << item
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ QML.application do |app|
35
+ app.load_path Pathname(__FILE__) + '../main.qml'
36
+ end
@@ -0,0 +1,36 @@
1
+ import QtQuick 2.2
2
+ import QtQuick.Controls 1.1
3
+ import QtQuick.Layouts 1.1
4
+ import Examples.Twitter 0.1
5
+
6
+ ApplicationWindow {
7
+ visible: true
8
+ width: 200
9
+ height: 100
10
+ title: "Twitter Test"
11
+
12
+ ListView {
13
+ anchors.fill: parent
14
+ model: controller.model
15
+ delegate: RowLayout {
16
+ Image {
17
+ width: 100
18
+ height: 100
19
+ source: user_icon
20
+ }
21
+ ColumnLayout {
22
+ Text {
23
+ font.bold: true
24
+ text: user_name
25
+ }
26
+ Text {
27
+ text: tweet_text
28
+ }
29
+ }
30
+ }
31
+ }
32
+
33
+ TwitterController {
34
+ id: controller
35
+ }
36
+ }
@@ -0,0 +1,55 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__)
2
+ require 'qml'
3
+ require 'twitter'
4
+ require 'yaml'
5
+
6
+ module Examples
7
+ module Twitter
8
+ VERSION = '0.1'
9
+
10
+ class TwitterModel < QML::Data::ArrayModel
11
+ column :tweet_text, :user_name, :user_icon
12
+ end
13
+
14
+ class TwitterController
15
+ include QML::Access
16
+ register_to_qml
17
+
18
+ property :model, TwitterModel.new
19
+
20
+ def initialize
21
+ super()
22
+
23
+ streaming_client = ::Twitter::Streaming::Client.new do |config|
24
+ data = YAML.load((Pathname(__FILE__) + '../config.yml').read)
25
+ %w{consumer_key consumer_secret access_token access_token_secret}.each do |key|
26
+ config.public_send("#{key}=", data[key])
27
+ end
28
+ end
29
+
30
+ Thread.new do
31
+ begin
32
+ streaming_client.user do |object|
33
+ case object
34
+ when ::Twitter::Tweet
35
+ later.add_tweet(object)
36
+ end
37
+ end
38
+ rescue => e
39
+ puts e.message
40
+ end
41
+ end
42
+ end
43
+
44
+ def add_tweet(tweet)
45
+ hash = {tweet_text: tweet.text, user_name: tweet.user.name, user_icon: tweet.user.profile_image_uri.to_s}
46
+ puts hash
47
+ model.unshift hash
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ QML.application do |app|
54
+ app.load_path Pathname(__FILE__) + '../main.qml'
55
+ end
@@ -0,0 +1,71 @@
1
+ #include "accessclass.h"
2
+ #include "accessobject.h"
3
+ #include "util.h"
4
+ #include <QDebug>
5
+
6
+ namespace RubyQml {
7
+
8
+ AccessClass::AccessClass(RubyValue className, RubyValue methodInfos, RubyValue signalInfos, RubyValue propertyInfos)
9
+ {
10
+ setClassName(className.to<QByteArray>());
11
+ protect([&] {
12
+ rb_check_array_type(methodInfos);
13
+ rb_check_array_type(signalInfos);
14
+ rb_check_array_type(propertyInfos);
15
+ });
16
+ for (int i = 0; i < RARRAY_LEN(VALUE(methodInfos)); ++i) {
17
+ RubyValue info = RARRAY_AREF(VALUE(methodInfos), i);
18
+ auto nameSym = info.send("name");
19
+ addMethod(nameSym.to<QByteArray>(),
20
+ nameSym.toID(),
21
+ info.send("params").to<QList<QByteArray>>());
22
+ }
23
+ for (int i = 0; i < RARRAY_LEN(VALUE(signalInfos)); ++i) {
24
+ RubyValue info = RARRAY_AREF(VALUE(signalInfos), i);
25
+ auto nameSym = info.send("name");
26
+ addSignal(nameSym.to<QByteArray>(),
27
+ nameSym.toID(),
28
+ info.send("params").to<QList<QByteArray>>());
29
+ }
30
+ for (int i = 0; i < RARRAY_LEN(VALUE(propertyInfos)); ++i) {
31
+ RubyValue info = RARRAY_AREF(VALUE(propertyInfos), i);
32
+ addProperty(info.send("name").to<QByteArray>(),
33
+ info.send("getter").toID(),
34
+ info.send("setter").toID(),
35
+ Property::Flag::Readable | Property::Flag::Writable,
36
+ true,
37
+ info.send("notifier").toID());
38
+ }
39
+ }
40
+
41
+ QVariant AccessClass::callMethod(ForeignObject *obj, size_t id, const QVariantList &args)
42
+ {
43
+ auto self = static_cast<AccessWrapper *>(obj)->wrappedValue();
44
+ QVariant ret;
45
+ withGvl([&] {
46
+ std::vector<VALUE> values(args.size());
47
+ std::transform(args.begin(), args.end(), values.begin(), &RubyValue::from<QVariant>);
48
+ RubyValue retValue;
49
+ protect([&] {
50
+ rescue([&] {
51
+ retValue = rb_funcall2(self, id, values.size(), values.data());
52
+ }, [&](RubyValue excObject) {
53
+ rb_funcall(rb_path2class("QML::Application"), rb_intern("notify_error"), 1, excObject);
54
+ });
55
+ });
56
+ ret = retValue.to<QVariant>();
57
+ });
58
+ return ret;
59
+ }
60
+
61
+ void AccessClass::setProperty(ForeignObject *obj, size_t id, const QVariant &variant)
62
+ {
63
+ callMethod(obj, id, {variant});
64
+ }
65
+
66
+ QVariant AccessClass::getProperty(ForeignObject *obj, size_t id)
67
+ {
68
+ return callMethod(obj, id, {});
69
+ }
70
+
71
+ } // namespace RubyQml