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