qml 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,126 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'qml/qt_object_base'
|
3
|
+
require 'qml/qml'
|
4
|
+
require 'qml/name_helper'
|
5
|
+
|
6
|
+
module QML
|
7
|
+
|
8
|
+
class QtProperty
|
9
|
+
prepend Reactive::Bindable
|
10
|
+
|
11
|
+
attr_reader :changed
|
12
|
+
|
13
|
+
def initialize(metaobj, objptr, name)
|
14
|
+
super()
|
15
|
+
@metaobj = metaobj
|
16
|
+
@objptr = objptr
|
17
|
+
@name = name
|
18
|
+
@changed = QtSignal.new(metaobj, objptr, @metaobj.notify_signal(@name))
|
19
|
+
end
|
20
|
+
|
21
|
+
def value=(newval)
|
22
|
+
@metaobj.set_property(@objptr, @name, newval)
|
23
|
+
end
|
24
|
+
|
25
|
+
def value
|
26
|
+
@metaobj.get_property(@objptr, @name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class QtSignal < Reactive::Signal
|
31
|
+
def initialize(metaobj, objptr, name)
|
32
|
+
super(variadic: true)
|
33
|
+
@objptr = objptr
|
34
|
+
@metaobj = metaobj
|
35
|
+
@name = name
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def connected(block)
|
41
|
+
return if @initialized
|
42
|
+
@metaobj.connect_signal(@objptr, @name, method(:emit))
|
43
|
+
@initialized = true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class ClassBuilder
|
48
|
+
|
49
|
+
attr_reader :metaobj, :klass
|
50
|
+
|
51
|
+
def initialize(metaobj, klass)
|
52
|
+
@metaobj = metaobj
|
53
|
+
@klass = klass
|
54
|
+
end
|
55
|
+
|
56
|
+
def build
|
57
|
+
create unless @klass
|
58
|
+
return if @klass.meta_object == @metaobj
|
59
|
+
|
60
|
+
@metaobj.method_names.reject { |name| @metaobj.signal?(name) }.each do |name|
|
61
|
+
define_method(name)
|
62
|
+
end
|
63
|
+
@metaobj.method_names.select { |name| @metaobj.signal?(name) }.each do |name|
|
64
|
+
define_signal(name)
|
65
|
+
end
|
66
|
+
@metaobj.property_names.each do |name|
|
67
|
+
define_property(name)
|
68
|
+
end
|
69
|
+
@metaobj.enumerators.each do |k, v|
|
70
|
+
define_enum(k, v)
|
71
|
+
end
|
72
|
+
@klass.__send__ :meta_object=, @metaobj
|
73
|
+
|
74
|
+
self
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def create
|
80
|
+
super_metaobj = @metaobj.super_class
|
81
|
+
@klass = Class.new(super_metaobj ? super_metaobj.build_class : QtObjectBase)
|
82
|
+
end
|
83
|
+
|
84
|
+
def define_method(name)
|
85
|
+
metaobj = @metaobj
|
86
|
+
return if metaobj.private?(name)
|
87
|
+
@klass.__send__ :define_method, name do |*args|
|
88
|
+
metaobj.invoke_method(@pointer, name, args)
|
89
|
+
end
|
90
|
+
@klass.__send__ :private, name if @metaobj.protected?(name)
|
91
|
+
underscore = NameHelper.to_underscore(name)
|
92
|
+
@klass.__send__ :alias_method, underscore, name if underscore != name
|
93
|
+
end
|
94
|
+
|
95
|
+
def define_signal(name)
|
96
|
+
@klass.__send__ :variadic_signal, name, factory: proc { |obj|
|
97
|
+
QtSignal.new(@metaobj, obj.pointer, name)
|
98
|
+
}
|
99
|
+
underscore = NameHelper.to_underscore(name)
|
100
|
+
@klass.__send__ :alias_signal, underscore, name if underscore != name
|
101
|
+
end
|
102
|
+
|
103
|
+
def define_property(name)
|
104
|
+
metaobj = @metaobj
|
105
|
+
@klass.__send__ :property, name, factory: proc { |obj|
|
106
|
+
QtProperty.new(@metaobj, obj.pointer, name)
|
107
|
+
}
|
108
|
+
underscore = NameHelper.to_underscore(name)
|
109
|
+
@klass.__send__ :alias_property, underscore, name if underscore != name
|
110
|
+
end
|
111
|
+
|
112
|
+
def define_enum(name, hash)
|
113
|
+
define_const(name, hash.values.sort)
|
114
|
+
hash.each do |k, v|
|
115
|
+
define_const(k, v)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def define_const(name, value)
|
120
|
+
name = (name[0].capitalize + name[1..-1]).to_sym
|
121
|
+
@klass.__send__ :const_set, name, value
|
122
|
+
underscore = NameHelper.to_upper_underscore(name)
|
123
|
+
@klass.__send__ :const_set, underscore, value if underscore != name
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'qml/engine'
|
2
|
+
|
3
|
+
module QML
|
4
|
+
# @!parse class Component < QtObjectBase; end
|
5
|
+
|
6
|
+
# The Component class is used to instantiate objects like Window / ApplicationWindow objects from QML files.
|
7
|
+
#
|
8
|
+
# You usually do not need to use this class because Application#load, #load_path, #load_data do same
|
9
|
+
# for the application top-level objects such as main windows.
|
10
|
+
# @example
|
11
|
+
# component = Component.new(path: path_to_qml_file)
|
12
|
+
# root_object = component.create
|
13
|
+
# @see http://qt-project.org/doc/qt-5/qqmlcomponent.html QQmlComponent (C++)
|
14
|
+
class Component
|
15
|
+
attr_reader :data, :path, :context
|
16
|
+
|
17
|
+
# Creates an component. Either data or path must be specified.
|
18
|
+
# @param context [QML::Context|nil] The context that the created objects will depend on (default to the root context of the application engine)
|
19
|
+
# @param data [String] The QML file data
|
20
|
+
# @param path [#to_s] The QML file path
|
21
|
+
# @return QML::Component
|
22
|
+
def self.new(context: nil, data: nil, path: nil)
|
23
|
+
context ||= Engine.instance.context
|
24
|
+
Plugins.core.createComponent(Engine.instance).instance_eval do
|
25
|
+
@data = data
|
26
|
+
@path = path
|
27
|
+
@context = context
|
28
|
+
|
29
|
+
if data
|
30
|
+
@extension.loadString(data, (path && path.to_s) || '')
|
31
|
+
elsif path
|
32
|
+
@extension.loadFile(path.to_s)
|
33
|
+
else
|
34
|
+
fail QMLError, 'neither data nor path specified'
|
35
|
+
end
|
36
|
+
|
37
|
+
self
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize
|
42
|
+
super()
|
43
|
+
Access.register_classes
|
44
|
+
@extension = Plugins.core.createComponentExtension(self)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Instantiates a object from the QML file.
|
48
|
+
# @return [QtObjectBase] The created Qt object
|
49
|
+
def create
|
50
|
+
@extension.create(@context)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/qml/context.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'qml/qt_classes'
|
2
|
+
|
3
|
+
module QML
|
4
|
+
# @!parse class Context < QtObjectBase; end
|
5
|
+
|
6
|
+
# {Context} represents QML contexts and used to expose Ruby values to QML.
|
7
|
+
# Each context has values that is called "context properties" that can be accessed in QML by their names.
|
8
|
+
#
|
9
|
+
# This class is automatically created from QQmlContext (C++).
|
10
|
+
# @see http://qt-project.org/doc/qt-5/qqmlcontext.html QQmlContext(C++)
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# QML.application do |app|
|
14
|
+
# app.context[:foo] = 'foo'
|
15
|
+
# app.context[:bar] = 'bar'
|
16
|
+
# ...
|
17
|
+
# end
|
18
|
+
class Context
|
19
|
+
|
20
|
+
# Creates a new instance of {Context}.
|
21
|
+
def self.new
|
22
|
+
Plugins.core.createContext(Engine.instance)
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
super()
|
27
|
+
@extension = Plugins.core.createContextExtension(self)
|
28
|
+
@context_properties = {}
|
29
|
+
end
|
30
|
+
|
31
|
+
# Evaluates an JavaScript expression on the object in this context.
|
32
|
+
# @param obj The object the expression is evaluated on
|
33
|
+
# @param str The JavaScript expression string
|
34
|
+
# @see QtObjectBase#qml_eval
|
35
|
+
def eval(obj, str)
|
36
|
+
@extension.evaluate(obj, str)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Sets a context property.
|
40
|
+
# @param key [String|Symbol] The property key
|
41
|
+
# @param value The value
|
42
|
+
# @return The value
|
43
|
+
def []=(key, value)
|
44
|
+
# be sure that the value is managed when it is a QObject
|
45
|
+
value = value.create_wrapper if value.is_a? Wrappable
|
46
|
+
value.prefer_managed true if value.is_a? QtObjectBase
|
47
|
+
|
48
|
+
# hold referenece because QQmlContext::setContextProperty does not take ownership of objects
|
49
|
+
@context_properties[key] = value
|
50
|
+
|
51
|
+
@extension.setContextProperty(key, value)
|
52
|
+
value
|
53
|
+
end
|
54
|
+
|
55
|
+
# Gets a context property.
|
56
|
+
# @param key [String|Symbol] The property key
|
57
|
+
# @return The value
|
58
|
+
def [](key)
|
59
|
+
@extension.contextProperty(key)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Gets a context that an object belongs to. If the object belongs to no context, returns nil.
|
63
|
+
# @param obj
|
64
|
+
# @return [Context|nil]
|
65
|
+
def self.for_object(obj)
|
66
|
+
Plugins.core.contextForObject(obj).tap do |context|
|
67
|
+
context.managed = false if context
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/qml/data.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
module QML
|
2
|
+
module Data
|
3
|
+
# {ArrayModel} is one of ruby-qml's list models and it stores data in Array simply.
|
4
|
+
class ArrayModel < ListModel
|
5
|
+
def initialize
|
6
|
+
super()
|
7
|
+
@array = []
|
8
|
+
end
|
9
|
+
|
10
|
+
# Duplicates the internal array and returns it.
|
11
|
+
# @return [Array]
|
12
|
+
def to_a
|
13
|
+
@array.dup
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Integer] the number of the items.
|
17
|
+
def count
|
18
|
+
@array.count
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns an item.
|
22
|
+
# @param [Integer] index the index of the item.
|
23
|
+
# @return the item.
|
24
|
+
def [](index)
|
25
|
+
@array[index]
|
26
|
+
end
|
27
|
+
|
28
|
+
# Updates an item.
|
29
|
+
# @param [Integer] index
|
30
|
+
# @param item
|
31
|
+
# @return the item.
|
32
|
+
def []=(index, item)
|
33
|
+
@array[index] = item
|
34
|
+
update(index .. index)
|
35
|
+
item
|
36
|
+
end
|
37
|
+
|
38
|
+
# Inserts items.
|
39
|
+
# @param [Integer] index
|
40
|
+
# @return [self]
|
41
|
+
def insert(index, *items)
|
42
|
+
inserting(index ... index + items.size) do
|
43
|
+
@array.insert(index, *items)
|
44
|
+
end
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
# @overload delete_at(index)
|
49
|
+
# Deletes an item.
|
50
|
+
# @param [Integer] index
|
51
|
+
# @return the deleted item.
|
52
|
+
# @overload delete_at(index, count)
|
53
|
+
# Deletes items.
|
54
|
+
# @param [Integer] index
|
55
|
+
# @return [Array] the deleted items.
|
56
|
+
def delete_at(index, count = nil)
|
57
|
+
if count
|
58
|
+
removing(index ... index + count) do
|
59
|
+
count.times.map { @array.delete_at(index) }
|
60
|
+
end
|
61
|
+
else
|
62
|
+
removing(index .. index) do
|
63
|
+
@array.delete_at(index)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Prepend items.
|
69
|
+
# @return [self]
|
70
|
+
def unshift(*items)
|
71
|
+
insert(0, *items)
|
72
|
+
end
|
73
|
+
|
74
|
+
# @overload shift
|
75
|
+
# Deletes the first item.
|
76
|
+
# @return the deleted item.
|
77
|
+
# @overload shift(count)
|
78
|
+
# Deletes the first items.
|
79
|
+
# @return [Array] the deleted items.
|
80
|
+
def shift(count = nil)
|
81
|
+
delete_at(0, count)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Append items.
|
85
|
+
# @return [self]
|
86
|
+
def push(*items)
|
87
|
+
insert(@array.size, *items)
|
88
|
+
end
|
89
|
+
|
90
|
+
alias_method :<<, :push
|
91
|
+
|
92
|
+
# @overload pop
|
93
|
+
# Deletes the last item.
|
94
|
+
# @return the deleted item.
|
95
|
+
# @overload pop(count)
|
96
|
+
# Deletes the last items.
|
97
|
+
# @return [Array] the deleted items.
|
98
|
+
def pop(count = nil)
|
99
|
+
delete_at(@array.size - count, count)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'qml/data/error'
|
2
|
+
require 'qml/wrappable'
|
3
|
+
require 'qml/dispatchable'
|
4
|
+
|
5
|
+
module QML
|
6
|
+
module Data
|
7
|
+
# {ListModel} is the base class of list models which provides data to QML list views.
|
8
|
+
# @see http://qt-project.org/doc/qt-5/qabstractitemmodel.html QAbstractItemModel (C++)
|
9
|
+
# @see http://qt-project.org/doc/qt-5/qabstractlistmodel.html QAbstractListModel (C++)
|
10
|
+
class ListModel
|
11
|
+
include ::Enumerable
|
12
|
+
include Wrappable
|
13
|
+
include Dispatchable
|
14
|
+
|
15
|
+
class << self
|
16
|
+
# Declares the columns of the model.
|
17
|
+
# @param [Array<Symbol|String>] columns
|
18
|
+
def column(*columns)
|
19
|
+
@columns ||= []
|
20
|
+
@columns |= columns
|
21
|
+
end
|
22
|
+
|
23
|
+
# The columns of the model.
|
24
|
+
attr_reader :columns
|
25
|
+
end
|
26
|
+
|
27
|
+
# @api private
|
28
|
+
# @return [Array<QtObjectBase>]
|
29
|
+
attr_reader :qt_models
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
fail Error, 'columns not specified' unless self.class.columns
|
33
|
+
@qt_models = []
|
34
|
+
end
|
35
|
+
|
36
|
+
# Iterates each item.
|
37
|
+
# @overload each
|
38
|
+
# @return [Enumerator]
|
39
|
+
# @overload each
|
40
|
+
# @yield [item]
|
41
|
+
# @return [self]
|
42
|
+
def each
|
43
|
+
return to_enum unless block_given?
|
44
|
+
count.times do |i|
|
45
|
+
yield self[i]
|
46
|
+
end
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
# @abstract
|
51
|
+
# @return [Integer] the number of the items.
|
52
|
+
def count
|
53
|
+
fail ::NotImplementedError
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns an item.
|
57
|
+
# @abstract
|
58
|
+
# @param [Integer] index the index of the item.
|
59
|
+
# @return the item.
|
60
|
+
def [](index)
|
61
|
+
fail ::NotImplementedError
|
62
|
+
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
|
66
|
+
# Notifies the list views that the data of the items was changed.
|
67
|
+
# @param [Range<Integer>] range the index range of changed items.
|
68
|
+
def update(range)
|
69
|
+
@qt_models.each do |qt_model|
|
70
|
+
qt_model.update(range.min, range.max)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Notifies the list views that items are about to be and were moved.
|
75
|
+
# @param [Range<Integer>] range the index range of the item being moved.
|
76
|
+
# @param [Integer] destination the first index of the items after moved.
|
77
|
+
# @yield the block that actually do moving operation of the items.
|
78
|
+
# @return the result of given block.
|
79
|
+
# @see http://qt-project.org/doc/qt-5/qabstractitemmodel.html#beginMoveRows QAbstractItemModel::beginMoveRows
|
80
|
+
# @see http://qt-project.org/doc/qt-5/qabstractitemmodel.html#endMoveRows QAbstractItemModel::endMoveRows
|
81
|
+
# @see #inserting
|
82
|
+
# @see #removing
|
83
|
+
def moving(range, destination, &block)
|
84
|
+
@qt_models.each do |qt_model|
|
85
|
+
qt_model.begin_move(range.min, range.max, destination)
|
86
|
+
end
|
87
|
+
|
88
|
+
ret = block.call
|
89
|
+
|
90
|
+
@qt_models.each do |qt_model|
|
91
|
+
qt_model.end_move
|
92
|
+
end
|
93
|
+
|
94
|
+
ret
|
95
|
+
end
|
96
|
+
|
97
|
+
# Notifies the list views that items are about to be and were inserted.
|
98
|
+
# @param [Range<Integer>] range the index range of the items after inserted.
|
99
|
+
# @yield the block that actually do insertion of the items.
|
100
|
+
# @return the result of give block.
|
101
|
+
# @example
|
102
|
+
# inserting(index ... index + items.size) do
|
103
|
+
# @array.insert(index, *items)
|
104
|
+
# end
|
105
|
+
# @see http://qt-project.org/doc/qt-5/qabstractitemmodel.html#beginInsertRows QAbstractItemModel::beginInsertRows
|
106
|
+
# @see http://qt-project.org/doc/qt-5/qabstractitemmodel.html#endInsertRows QAbstractItemModel::endInsertRows
|
107
|
+
# @see #removing
|
108
|
+
# @see #moving
|
109
|
+
def inserting(range, &block)
|
110
|
+
@qt_models.each do |qt_model|
|
111
|
+
qt_model.begin_insert(range.min, range.max)
|
112
|
+
end
|
113
|
+
|
114
|
+
ret = block.call
|
115
|
+
|
116
|
+
@qt_models.each do |qt_model|
|
117
|
+
qt_model.end_insert
|
118
|
+
end
|
119
|
+
|
120
|
+
ret
|
121
|
+
end
|
122
|
+
|
123
|
+
# Notifies the list views that items are about to be and were removed.
|
124
|
+
# @param [Range<Integer>] range the index range of the items before removed.
|
125
|
+
# @yield the block that actually do removal of the items.
|
126
|
+
# @return the result of give block.
|
127
|
+
# @see http://qt-project.org/doc/qt-5/qabstractitemmodel.html#beginRemoveRows QAbstractItemModel::beginRemoveRows
|
128
|
+
# @see http://qt-project.org/doc/qt-5/qabstractitemmodel.html#endRemoveRows QAbstractItemModel::endRemoveRows
|
129
|
+
# @see #inserting
|
130
|
+
# @see #moving
|
131
|
+
def removing(range, &block)
|
132
|
+
@qt_models.each do |qt_model|
|
133
|
+
qt_model.begin_remove(range.min, range.max)
|
134
|
+
end
|
135
|
+
|
136
|
+
ret = block.call
|
137
|
+
|
138
|
+
@qt_models.each do |qt_model|
|
139
|
+
qt_model.end_remove
|
140
|
+
end
|
141
|
+
|
142
|
+
ret
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|