qml 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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