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.
- checksums.yaml +7 -0
- data/.gitignore +46 -0
- data/.rspec +2 -0
- data/.travis.yml +15 -0
- data/.yardopts +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +351 -0
- data/Rakefile +6 -0
- data/examples/assets/fonts/fontawesome-webfont.ttf +0 -0
- data/examples/fizzbuzz/fizzbuzz.rb +43 -0
- data/examples/fizzbuzz/main.qml +38 -0
- data/examples/imageprovider/imageprovider.rb +57 -0
- data/examples/imageprovider/main.qml +51 -0
- data/examples/todo/main.qml +70 -0
- data/examples/todo/todo.rb +36 -0
- data/examples/twitter/main.qml +36 -0
- data/examples/twitter/twitter.rb +55 -0
- data/ext/qml/accessclass.cpp +71 -0
- data/ext/qml/accessclass.h +19 -0
- data/ext/qml/accessobject.cpp +30 -0
- data/ext/qml/accessobject.h +22 -0
- data/ext/qml/application.cpp +54 -0
- data/ext/qml/application.h +17 -0
- data/ext/qml/common.h +18 -0
- data/ext/qml/ext_accesssupport.cpp +77 -0
- data/ext/qml/ext_accesssupport.h +42 -0
- data/ext/qml/ext_gcmarker.cpp +39 -0
- data/ext/qml/ext_gcmarker.h +27 -0
- data/ext/qml/ext_kernel.cpp +62 -0
- data/ext/qml/ext_kernel.h +11 -0
- data/ext/qml/ext_metaobject.cpp +410 -0
- data/ext/qml/ext_metaobject.h +62 -0
- data/ext/qml/ext_pluginloader.cpp +55 -0
- data/ext/qml/ext_pluginloader.h +32 -0
- data/ext/qml/ext_pointer.cpp +134 -0
- data/ext/qml/ext_pointer.h +43 -0
- data/ext/qml/ext_testutil.cpp +42 -0
- data/ext/qml/ext_testutil.h +11 -0
- data/ext/qml/extconf.rb +84 -0
- data/ext/qml/foreignclass.cpp +72 -0
- data/ext/qml/foreignclass.h +88 -0
- data/ext/qml/foreignmetaobject.cpp +345 -0
- data/ext/qml/foreignmetaobject.h +46 -0
- data/ext/qml/foreignobject.cpp +22 -0
- data/ext/qml/foreignobject.h +21 -0
- data/ext/qml/functioninfo.h +16 -0
- data/ext/qml/init.cpp +69 -0
- data/ext/qml/listmodel.cpp +112 -0
- data/ext/qml/listmodel.h +43 -0
- data/ext/qml/markable.h +12 -0
- data/ext/qml/objectdata.cpp +26 -0
- data/ext/qml/objectdata.h +20 -0
- data/ext/qml/objectgc.cpp +69 -0
- data/ext/qml/objectgc.h +28 -0
- data/ext/qml/plugins/core/applicationextension.cpp +34 -0
- data/ext/qml/plugins/core/applicationextension.h +28 -0
- data/ext/qml/plugins/core/componentextension.cpp +41 -0
- data/ext/qml/plugins/core/componentextension.h +28 -0
- data/ext/qml/plugins/core/contextextension.cpp +39 -0
- data/ext/qml/plugins/core/contextextension.h +29 -0
- data/ext/qml/plugins/core/core.pro +29 -0
- data/ext/qml/plugins/core/coreplugin.cpp +87 -0
- data/ext/qml/plugins/core/coreplugin.h +49 -0
- data/ext/qml/plugins/core/engineextension.cpp +27 -0
- data/ext/qml/plugins/core/engineextension.h +28 -0
- data/ext/qml/plugins/core/imageprovider.cpp +38 -0
- data/ext/qml/plugins/core/imageprovider.h +18 -0
- data/ext/qml/plugins/core/imagerequestpromise.cpp +19 -0
- data/ext/qml/plugins/core/imagerequestpromise.h +21 -0
- data/ext/qml/plugins/core/qmlexception.cpp +11 -0
- data/ext/qml/plugins/core/qmlexception.h +17 -0
- data/ext/qml/plugins/testutil/objectlifechecker.cpp +17 -0
- data/ext/qml/plugins/testutil/objectlifechecker.h +24 -0
- data/ext/qml/plugins/testutil/ownershiptest.cpp +26 -0
- data/ext/qml/plugins/testutil/ownershiptest.h +30 -0
- data/ext/qml/plugins/testutil/testobject.cpp +6 -0
- data/ext/qml/plugins/testutil/testobject.h +108 -0
- data/ext/qml/plugins/testutil/testobjectsubclass.cpp +10 -0
- data/ext/qml/plugins/testutil/testobjectsubclass.h +19 -0
- data/ext/qml/plugins/testutil/testutil.pro +20 -0
- data/ext/qml/plugins/testutil/testutilplugin.cpp +47 -0
- data/ext/qml/plugins/testutil/testutilplugin.h +32 -0
- data/ext/qml/qmltyperegisterer.cpp +74 -0
- data/ext/qml/qmltyperegisterer.h +30 -0
- data/ext/qml/rubyclass.cpp +94 -0
- data/ext/qml/rubyclass.h +234 -0
- data/ext/qml/rubyvalue.cpp +690 -0
- data/ext/qml/rubyvalue.h +256 -0
- data/ext/qml/signalforwarder.cpp +66 -0
- data/ext/qml/signalforwarder.h +29 -0
- data/ext/qml/util.cpp +120 -0
- data/ext/qml/util.h +101 -0
- data/ext/qml/valuereference.cpp +50 -0
- data/ext/qml/valuereference.h +22 -0
- data/ext/qml/weakvaluereference.cpp +27 -0
- data/ext/qml/weakvaluereference.h +19 -0
- data/lib/qml.rb +41 -0
- data/lib/qml/access.rb +137 -0
- data/lib/qml/application.rb +139 -0
- data/lib/qml/class_builder.rb +126 -0
- data/lib/qml/component.rb +53 -0
- data/lib/qml/context.rb +71 -0
- data/lib/qml/data.rb +2 -0
- data/lib/qml/data/array_model.rb +103 -0
- data/lib/qml/data/error.rb +5 -0
- data/lib/qml/data/list_model.rb +146 -0
- data/lib/qml/dispatchable.rb +34 -0
- data/lib/qml/dispatcher.rb +61 -0
- data/lib/qml/engine.rb +54 -0
- data/lib/qml/error_converter.rb +15 -0
- data/lib/qml/errors.rb +26 -0
- data/lib/qml/geometry.rb +3 -0
- data/lib/qml/geometry/point.rb +5 -0
- data/lib/qml/geometry/rectangle.rb +5 -0
- data/lib/qml/geometry/size.rb +5 -0
- data/lib/qml/image_provider.rb +87 -0
- data/lib/qml/meta_object.rb +20 -0
- data/lib/qml/models.rb +1 -0
- data/lib/qml/name_helper.rb +12 -0
- data/lib/qml/platform.rb +15 -0
- data/lib/qml/plugin_loader.rb +46 -0
- data/lib/qml/plugins.rb +26 -0
- data/lib/qml/qml.rb +1 -0
- data/lib/qml/qt.rb +6 -0
- data/lib/qml/qt_classes.rb +9 -0
- data/lib/qml/qt_object_base.rb +108 -0
- data/lib/qml/reactive.rb +8 -0
- data/lib/qml/reactive/bindable.rb +79 -0
- data/lib/qml/reactive/chained_signal.rb +25 -0
- data/lib/qml/reactive/error.rb +5 -0
- data/lib/qml/reactive/object.rb +278 -0
- data/lib/qml/reactive/property.rb +19 -0
- data/lib/qml/reactive/signal.rb +116 -0
- data/lib/qml/reactive/signal_spy.rb +27 -0
- data/lib/qml/reactive/signals/map_signal.rb +21 -0
- data/lib/qml/reactive/signals/merge_signal.rb +21 -0
- data/lib/qml/reactive/signals/select_signal.rb +21 -0
- data/lib/qml/reactive/simple_property.rb +17 -0
- data/lib/qml/reactive/unbound_property.rb +42 -0
- data/lib/qml/reactive/unbound_signal.rb +51 -0
- data/lib/qml/root_path.rb +3 -0
- data/lib/qml/test_util.rb +1 -0
- data/lib/qml/test_util/object_life_checker.rb +17 -0
- data/lib/qml/version.rb +3 -0
- data/lib/qml/wrappable.rb +9 -0
- data/qml.gemspec +28 -0
- data/spec/assets/testobj.qml +5 -0
- data/spec/qml/.access_spec.rb.swp +0 -0
- data/spec/qml/access_spec.rb +162 -0
- data/spec/qml/application_spec.rb +43 -0
- data/spec/qml/component_spec.rb +44 -0
- data/spec/qml/context_spec.rb +43 -0
- data/spec/qml/conversion_spec.rb +59 -0
- data/spec/qml/data/array_model_spec.rb +215 -0
- data/spec/qml/dispatchable_spec.rb +26 -0
- data/spec/qml/dispatcher_spec.rb +48 -0
- data/spec/qml/geometry/point_spec.rb +4 -0
- data/spec/qml/geometry/rectangle_spec.rb +4 -0
- data/spec/qml/geometry/size_spec.rb +4 -0
- data/spec/qml/plugin_loader_spec.rb +33 -0
- data/spec/qml/qt_object_base_spec.rb +119 -0
- data/spec/qml/reactive/object_spec.rb +273 -0
- data/spec/qml/reactive/property_spec.rb +70 -0
- data/spec/qml/reactive/signal_spec.rb +191 -0
- data/spec/qml/reactive/signal_spy_spec.rb +26 -0
- data/spec/qml/test_object_spec.rb +186 -0
- data/spec/qml_spec.rb +7 -0
- data/spec/spec_helper.rb +5 -0
- metadata +321 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe QML::PluginLoader do
|
|
4
|
+
|
|
5
|
+
let(:loader) { QML::PluginLoader.new path, 'rubyqml-testutil' }
|
|
6
|
+
|
|
7
|
+
describe 'load' do
|
|
8
|
+
|
|
9
|
+
context 'with signle path' do
|
|
10
|
+
let(:path) { QML::ROOT_PATH + 'ext/qml/plugins/testutil' + QML::PluginLoader.lib_filename('rubyqml-testutil') }
|
|
11
|
+
let(:loader) { QML::PluginLoader.new path }
|
|
12
|
+
it 'creates an object instance' do
|
|
13
|
+
loader.load
|
|
14
|
+
expect(loader.instance).to be_a QML::QtObjectBase
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context 'with correct file path' do
|
|
19
|
+
let(:path) { QML::ROOT_PATH + 'ext/qml/plugins/testutil' }
|
|
20
|
+
it 'creates an object instance' do
|
|
21
|
+
loader.load
|
|
22
|
+
expect(loader.instance).to be_a QML::QtObjectBase
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'with wrong file path' do
|
|
27
|
+
let(:path) { QML::ROOT_PATH + 'ext/qml/plugins/wrong' }
|
|
28
|
+
it 'fails with QML::PluginError' do
|
|
29
|
+
expect { loader.load }.to raise_error(QML::PluginError)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe QML::QtObjectBase do
|
|
4
|
+
|
|
5
|
+
describe '#qml_eval' do
|
|
6
|
+
|
|
7
|
+
let(:component) do
|
|
8
|
+
QML::Component.new data: <<-EOS
|
|
9
|
+
import QtQuick 2.0
|
|
10
|
+
QtObject {
|
|
11
|
+
property string foo: 'foo'
|
|
12
|
+
property string bar: 'bar'
|
|
13
|
+
}
|
|
14
|
+
EOS
|
|
15
|
+
end
|
|
16
|
+
let(:object) { component.create }
|
|
17
|
+
let(:expression) { 'foo + bar' }
|
|
18
|
+
let(:result) { object.qml_eval(expression) }
|
|
19
|
+
|
|
20
|
+
it 'evaluates a JS expression in its QML scope' do
|
|
21
|
+
expect(result).to eq 'foobar'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context 'when expression is wrong' do
|
|
25
|
+
let(:expression) { 'hoge + piyo' }
|
|
26
|
+
it 'raises QML::QMLError' do
|
|
27
|
+
expect { result }.to raise_error(QML::QMLError)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context 'when object does not belong to context' do
|
|
32
|
+
let(:object) { QML::Plugins.test_util.createTestObject }
|
|
33
|
+
it 'raises QML::QMLError' do
|
|
34
|
+
expect { result }.to raise_error(QML::QMLError)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe 'ownership' do
|
|
40
|
+
let(:ownership_test) { QML::Plugins.test_util.create_ownership_test }
|
|
41
|
+
|
|
42
|
+
context 'when it is returned from a method' do
|
|
43
|
+
it 'gets ownership of the object' do
|
|
44
|
+
checker = -> { QML::TestUtil::ObjectLifeChecker.new(ownership_test.create_object) }.call
|
|
45
|
+
QML.application.collect_garbage
|
|
46
|
+
expect(checker.alive?).to eq false
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context 'when it is obtained from a property' do
|
|
51
|
+
it 'does not get ownership of the object' do
|
|
52
|
+
checker = -> { QML::TestUtil::ObjectLifeChecker.new(ownership_test.property_object) }.call
|
|
53
|
+
QML.application.collect_garbage
|
|
54
|
+
expect(checker.alive?).to eq true
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context 'when it has a parent' do
|
|
59
|
+
it 'does not get ownership of the object' do
|
|
60
|
+
checker = -> { QML::TestUtil::ObjectLifeChecker.new(ownership_test.sub_object) }.call
|
|
61
|
+
QML.application.collect_garbage
|
|
62
|
+
expect(checker.alive?).to eq true
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
context 'when it is created by component' do
|
|
67
|
+
let(:component) do
|
|
68
|
+
QML::Component.new data: <<-EOS
|
|
69
|
+
import QtQuick 2.0
|
|
70
|
+
Item {}
|
|
71
|
+
EOS
|
|
72
|
+
end
|
|
73
|
+
it 'gets ownership' do
|
|
74
|
+
checker = -> { QML::TestUtil::ObjectLifeChecker.new(component.create) }.call
|
|
75
|
+
QML.application.collect_garbage
|
|
76
|
+
expect(checker.alive?).to eq false
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe '#managed?' do
|
|
81
|
+
[true, false].each do |cond|
|
|
82
|
+
context "when managed = #{cond}" do
|
|
83
|
+
it "returns #{cond}" do
|
|
84
|
+
obj = ownership_test.create_object
|
|
85
|
+
obj.managed = cond
|
|
86
|
+
expect(obj.managed?).to eq cond
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context 'on garbage collection' do
|
|
93
|
+
|
|
94
|
+
context 'when managed' do
|
|
95
|
+
it 'gets destroyed' do
|
|
96
|
+
checker = -> {
|
|
97
|
+
obj = ownership_test.create_object
|
|
98
|
+
obj.managed = true
|
|
99
|
+
QML::TestUtil::ObjectLifeChecker.new(obj)
|
|
100
|
+
}.call
|
|
101
|
+
QML.application.collect_garbage
|
|
102
|
+
expect(checker.alive?).to eq false
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
context 'when not managed' do
|
|
107
|
+
it 'does not get destroyed' do
|
|
108
|
+
checker = -> {
|
|
109
|
+
obj = ownership_test.create_object
|
|
110
|
+
obj.managed = false
|
|
111
|
+
QML::TestUtil::ObjectLifeChecker.new(obj)
|
|
112
|
+
}.call
|
|
113
|
+
QML.application.collect_garbage
|
|
114
|
+
expect(checker.alive?).to eq true
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe QML::Reactive::Object do
|
|
4
|
+
|
|
5
|
+
class Button
|
|
6
|
+
include QML::Reactive::Object
|
|
7
|
+
signal :pressed, [:pos]
|
|
8
|
+
variadic_signal :message
|
|
9
|
+
property :name, 'button'
|
|
10
|
+
property :id, 0
|
|
11
|
+
property :name_double do
|
|
12
|
+
name + name
|
|
13
|
+
end
|
|
14
|
+
on :pressed do |pos|
|
|
15
|
+
self.name = pos
|
|
16
|
+
end
|
|
17
|
+
on_changed :id do
|
|
18
|
+
self.name = "ID: #{id}"
|
|
19
|
+
end
|
|
20
|
+
on_changed :id do
|
|
21
|
+
end
|
|
22
|
+
alias_property :title, :name
|
|
23
|
+
alias_signal :clicked, :pressed
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class ToggleButton < Button
|
|
27
|
+
signal :pressed, [:x, :y]
|
|
28
|
+
signal :toggled, [:on]
|
|
29
|
+
property(:name) { 'toggle button' }
|
|
30
|
+
property(:info) { 'some info' }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
let(:button) { Button.new }
|
|
34
|
+
let(:toggle_button) { ToggleButton.new }
|
|
35
|
+
|
|
36
|
+
describe '.property' do
|
|
37
|
+
|
|
38
|
+
it 'defines getter' do
|
|
39
|
+
expect(button.name).to eq('button')
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'defines setter' do
|
|
43
|
+
button.name = 'hoge'
|
|
44
|
+
expect(button.name).to eq('hoge')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'can set property binding' do
|
|
48
|
+
button.name = 'poyo'
|
|
49
|
+
expect(button.name_double).to eq 'poyopoyo'
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'defines notify signal' do
|
|
53
|
+
spy = QML::Reactive::SignalSpy.new(button.name_changed)
|
|
54
|
+
button.name = 'hoge'
|
|
55
|
+
expect(spy.args.last).to eq(['hoge'])
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'returns the name' do
|
|
59
|
+
result = nil
|
|
60
|
+
Class.new do
|
|
61
|
+
include QML::Reactive::Object
|
|
62
|
+
result = property :foo
|
|
63
|
+
end
|
|
64
|
+
expect(result).to eq :foo
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context 'in subclass' do
|
|
68
|
+
|
|
69
|
+
it 'defines property in subclass' do
|
|
70
|
+
expect(toggle_button.info).to eq('some info')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'does not define property in superclass' do
|
|
74
|
+
expect(button.properties).not_to include(:info)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'overrides superclass property' do
|
|
78
|
+
expect(toggle_button.name).to eq('toggle button')
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
describe '.alias_property' do
|
|
84
|
+
it 'returns the name' do
|
|
85
|
+
result = nil
|
|
86
|
+
Class.new do
|
|
87
|
+
include QML::Reactive::Object
|
|
88
|
+
property :foo
|
|
89
|
+
result = alias_property :bar, :foo
|
|
90
|
+
end
|
|
91
|
+
expect(result).to eq :bar
|
|
92
|
+
end
|
|
93
|
+
it 'aliases a property' do
|
|
94
|
+
expect(button.property(:title)).to eq button.property(:name)
|
|
95
|
+
expect(button.signal(:title_changed)).to eq button.signal(:name_changed)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
describe '.signal' do
|
|
100
|
+
|
|
101
|
+
it 'defines a signal' do
|
|
102
|
+
spy = button.pressed.spy
|
|
103
|
+
button.pressed.emit([10, 22])
|
|
104
|
+
expect(spy.args.last).to eq([[10, 22]])
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'returns the name' do
|
|
108
|
+
result = nil
|
|
109
|
+
Class.new do
|
|
110
|
+
include QML::Reactive::Object
|
|
111
|
+
result = signal :sig, []
|
|
112
|
+
end
|
|
113
|
+
expect(result).to eq(:sig)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
context 'when the args parameter is not passed' do
|
|
117
|
+
it 'defines a variadic signal' do
|
|
118
|
+
spy = button.message.spy
|
|
119
|
+
button.message.emit(*%w{emitting some message})
|
|
120
|
+
expect(spy.args.last).to eq(%w{emitting some message})
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
context 'in subclass' do
|
|
125
|
+
|
|
126
|
+
it 'defines signal in subclass' do
|
|
127
|
+
spy = toggle_button.toggled.spy
|
|
128
|
+
toggle_button.toggled.emit(true)
|
|
129
|
+
expect(spy.args.last).to eq([true])
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it 'does not define signal in superclass' do
|
|
133
|
+
expect(button.signals).not_to include(:toggled)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it 'overrides superclass signal' do
|
|
137
|
+
signal = toggle_button.pressed
|
|
138
|
+
expect(signal.arity).to eq(2)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it 'defines overridden signal in subclass' do
|
|
142
|
+
spy = toggle_button.pressed.spy
|
|
143
|
+
toggle_button.pressed.emit(10, 20)
|
|
144
|
+
expect(spy.args.last).to eq([10, 20])
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
describe '.alias_signal' do
|
|
150
|
+
|
|
151
|
+
it 'returns the name' do
|
|
152
|
+
result = nil
|
|
153
|
+
Class.new do
|
|
154
|
+
include QML::Reactive::Object
|
|
155
|
+
signal :foo, []
|
|
156
|
+
result = alias_signal :bar, :foo
|
|
157
|
+
end
|
|
158
|
+
expect(result).to eq :bar
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it 'aliases a signal' do
|
|
162
|
+
expect(button.clicked).to eq button.pressed
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
describe '.on' do
|
|
167
|
+
it 'adds signal handler' do
|
|
168
|
+
button.pressed.emit "pressed at top"
|
|
169
|
+
expect(button.name).to eq "pressed at top"
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
describe '.on_changed' do
|
|
174
|
+
it 'add property changed signal handler' do
|
|
175
|
+
button.id = 2
|
|
176
|
+
expect(button.name).to eq "ID: 2"
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
describe '.instance_signals' do
|
|
181
|
+
context 'when include_super is false' do
|
|
182
|
+
it 'returns all signal definitions of the class' do
|
|
183
|
+
signals = ToggleButton.instance_signals(false)
|
|
184
|
+
expect(signals).to match_array %i{pressed toggled name_changed info_changed}
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
context 'when include_super is not specified' do
|
|
189
|
+
it 'returns all signal definitions of the class and its superclasses' do
|
|
190
|
+
signals = ToggleButton.instance_signals
|
|
191
|
+
expect(signals).to match_array %i{pressed message toggled name_changed id_changed info_changed name_double_changed clicked title_changed}
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
describe '.instance_properties' do
|
|
197
|
+
context 'when include_super is false' do
|
|
198
|
+
it 'returns all property definitions of the class' do
|
|
199
|
+
properties = ToggleButton.instance_properties(false)
|
|
200
|
+
expect(properties).to match_array %i{name info}
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
context 'when include_super is not specified' do
|
|
205
|
+
it 'returns all property definitions of the class and its superclasses' do
|
|
206
|
+
properties = ToggleButton.instance_properties
|
|
207
|
+
expect(properties).to match_array %i{name id info name_double title}
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
describe '.instance_signal' do
|
|
213
|
+
it 'returns the UnboundSignal for name' do
|
|
214
|
+
s = ToggleButton.instance_signal(:pressed)
|
|
215
|
+
expect(s).to be_a QML::Reactive::UnboundSignal
|
|
216
|
+
expect(s.name).to eq :pressed
|
|
217
|
+
expect(s.arity).to eq 2
|
|
218
|
+
end
|
|
219
|
+
context 'when signal does not exist' do
|
|
220
|
+
it 'fails with NameError' do
|
|
221
|
+
expect { ToggleButton.instance_signal(:non_existent) }.to raise_error(NameError)
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
describe '.instance_property' do
|
|
227
|
+
it 'returns the UnboundProperty for name' do
|
|
228
|
+
p = ToggleButton.instance_property(:name)
|
|
229
|
+
expect(p).to be_a QML::Reactive::UnboundProperty
|
|
230
|
+
expect(p.name).to eq :name
|
|
231
|
+
expect(p.initial_binding.call).to eq 'toggle button'
|
|
232
|
+
end
|
|
233
|
+
context 'when property does not exist' do
|
|
234
|
+
it 'fails with NameError' do
|
|
235
|
+
expect { ToggleButton.instance_property(:non_existent) }.to raise_error(NameError)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
describe '#signals' do
|
|
241
|
+
it 'returns signal names for object' do
|
|
242
|
+
expect(toggle_button.signals).to match_array %i{pressed message toggled id_changed name_changed info_changed name_double_changed clicked title_changed}
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
describe '#properties' do
|
|
247
|
+
it 'return property names for object' do
|
|
248
|
+
expect(toggle_button.properties).to match_array %i{name id info name_double title}
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
describe '#signal' do
|
|
253
|
+
it 'returns Signal for name' do
|
|
254
|
+
expect(toggle_button.signal(:pressed)).to eq toggle_button.pressed
|
|
255
|
+
end
|
|
256
|
+
context 'when signal does not exist' do
|
|
257
|
+
it 'fails with NameError' do
|
|
258
|
+
expect { toggle_button.signal(:non_existent) }.to raise_error(NameError)
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
describe '#property' do
|
|
264
|
+
it 'returns Property for name' do
|
|
265
|
+
expect(toggle_button.property(:name).value).to eq toggle_button.name
|
|
266
|
+
end
|
|
267
|
+
context 'when property does not exist' do
|
|
268
|
+
it 'fails with NameError' do
|
|
269
|
+
expect { toggle_button.property(:non_existent) }.to raise_error(NameError)
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe QML::Reactive::Property do
|
|
4
|
+
|
|
5
|
+
describe '#initialize' do
|
|
6
|
+
|
|
7
|
+
context 'when a value is given' do
|
|
8
|
+
it 'initializes with the value' do
|
|
9
|
+
p = QML::Reactive::Property.new(2)
|
|
10
|
+
expect(p.value).to eq(2)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context 'when a block is given' do
|
|
15
|
+
it 'initializes with the property binding' do
|
|
16
|
+
p1 = QML::Reactive::Property.new(2)
|
|
17
|
+
p2 = QML::Reactive::Property.new { p1.value + 2 }
|
|
18
|
+
p1.value = 10
|
|
19
|
+
expect(p2.value).to eq(12)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe 'access to the value' do
|
|
25
|
+
describe '#value, #value=' do
|
|
26
|
+
it 'sets and gets the contained value' do
|
|
27
|
+
property = QML::Reactive::Property.new
|
|
28
|
+
property.value = '(´・_・`)'
|
|
29
|
+
expect(property.value).to eq('(´・_・`)')
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe 'property binding' do
|
|
35
|
+
|
|
36
|
+
describe '#bind' do
|
|
37
|
+
|
|
38
|
+
it 'sets a property binding' do
|
|
39
|
+
p1 = QML::Reactive::Property.new 'foo'
|
|
40
|
+
p2 = QML::Reactive::Property.new 'bar'
|
|
41
|
+
p3 = QML::Reactive::Property.new
|
|
42
|
+
p4 = QML::Reactive::Property.new
|
|
43
|
+
p3.bind { p1.value + p2.value }
|
|
44
|
+
p4.bind { p3.value }
|
|
45
|
+
p1.value = 'hoge'
|
|
46
|
+
p2.value = 'piyo'
|
|
47
|
+
expect(p3.value).to eq('hogepiyo')
|
|
48
|
+
expect(p4.value).to eq('hogepiyo')
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context 'when binding is recursive' do
|
|
52
|
+
it 'raises error' do
|
|
53
|
+
property = QML::Reactive::Property.new
|
|
54
|
+
expect{ property.bind { property.value } }.to raise_error(QML::Reactive::Error)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe '#changed' do
|
|
61
|
+
it 'returns a signal that is emitted when the value is changed' do
|
|
62
|
+
property = QML::Reactive::Property.new
|
|
63
|
+
changed_value = nil
|
|
64
|
+
property.changed.connect { |val| changed_value = val }
|
|
65
|
+
|
|
66
|
+
property.value = 'piyopiyo'
|
|
67
|
+
expect(changed_value).to eq('piyopiyo')
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|