qml 0.0.1 → 0.0.2
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 +4 -4
- data/Gemfile +2 -0
- data/README.md +82 -19
- data/changes.md +17 -0
- data/examples/fizzbuzz/capture.png +0 -0
- data/examples/todo_array/capture.png +0 -0
- data/examples/{todo → todo_array}/main.qml +1 -1
- data/examples/{todo/todo.rb → todo_array/todo_array.rb} +4 -7
- data/examples/todo_sequel/capture.png +0 -0
- data/examples/todo_sequel/main.qml +87 -0
- data/examples/todo_sequel/todo_sequel.rb +66 -0
- data/examples/twitter/capture.png +0 -0
- data/examples/twitter/main.qml +31 -19
- data/examples/twitter/twitter.rb +46 -23
- data/ext/qml/accessclass.cpp +1 -3
- data/ext/qml/ext_anywrapper.cpp +36 -0
- data/ext/qml/ext_anywrapper.h +26 -0
- data/ext/qml/ext_metaobject.cpp +3 -1
- data/ext/qml/init.cpp +3 -3
- data/ext/qml/listmodel.cpp +29 -4
- data/ext/qml/listmodel.h +2 -0
- data/ext/qml/util.cpp +7 -0
- data/ext/qml/util.h +1 -0
- data/ext/qml/weakvaluereference.cpp +34 -9
- data/ext/qml/weakvaluereference.h +7 -5
- data/lib/qml/class_builder.rb +1 -0
- data/lib/qml/data.rb +1 -0
- data/lib/qml/data/array_model.rb +23 -2
- data/lib/qml/data/list_model.rb +26 -26
- data/lib/qml/data/query_model.rb +60 -0
- data/lib/qml/version.rb +1 -1
- data/qml.gemspec +5 -1
- data/spec/qml/data/array_model_spec.rb +43 -56
- data/spec/qml/data/list_model_spec.rb +17 -0
- data/spec/qml/data/query_model_spec.rb +62 -0
- data/spec/shared_examples/qml/data/list_model.rb +33 -0
- data/spec/spec_helper.rb +7 -0
- metadata +70 -30
- data/ext/qml/ext_gcmarker.cpp +0 -39
- data/ext/qml/ext_gcmarker.h +0 -27
- data/spec/qml/.access_spec.rb.swp +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31d0f1bbab5b1fa3d4b602baa55fc7df071f65a4
|
4
|
+
data.tar.gz: 4ba0b8cecc4f63b26f2284e56f132d19bd176c2b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29d4ae1d6ff4f3218cea47dd8d40b0b02441beb1a82f678138618c654dcc9ac0bf71f5cac6c11717ae13a6dc6d43cc1fab7fce3d061b01efe6761a308cba8c10
|
7
|
+
data.tar.gz: cb4a008e7083492d416a09d472668f67dc751db63ffd7d31d97d72726e9ec21610d4562e638c410548aaddedda3a1f2bc533bb2b0e7e021f4b9d77ec01e23ff1
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,14 +1,25 @@
|
|
1
1
|
# ruby-qml
|
2
2
|
|
3
|
+
[](http://badge.fury.io/rb/qml)
|
3
4
|
[](https://travis-ci.org/seanchas116/ruby-qml)
|
4
|
-
|
5
|
-
**NOTE: ruby-qml is not yet released as a gem.**
|
5
|
+
[](https://coveralls.io/r/seanchas116/ruby-qml?branch=master)
|
6
6
|
|
7
7
|
ruby-qml is a QML / Qt Quick wrapper for Ruby.
|
8
8
|
It provides bindings between QML and Ruby and enables you to use Qt Quick-based GUI from Ruby.
|
9
9
|
|
10
|
+
* [Documentation](http://rubydoc.info/github/seanchas116/ruby-qml/master/frames)
|
11
|
+
* [Examples](https://github.com/seanchas116/ruby-qml/tree/master/examples)
|
12
|
+
|
13
|
+
## Gallery
|
14
|
+
|
15
|
+
[](https://github.com/seanchas116/ruby-qml/tree/master/examples/todo_sequel)
|
16
|
+
|
17
|
+
[](https://github.com/seanchas116/ruby-qml/tree/master/examples/twitter)
|
18
|
+
|
10
19
|
## Installation
|
11
20
|
|
21
|
+
ruby-qml currently requires **Ruby 2.0 or later**.
|
22
|
+
|
12
23
|
### OS X with Homebrew
|
13
24
|
|
14
25
|
Run the following commands to install ruby-qml on OS X with Homebrew:
|
@@ -59,9 +70,8 @@ QML.application do |app|
|
|
59
70
|
end
|
60
71
|
```
|
61
72
|
|
62
|
-
#### main.qml
|
63
|
-
|
64
73
|
```qml
|
74
|
+
// main.qml
|
65
75
|
import QtQuick 2.2
|
66
76
|
import QtQuick.Controls 1.1
|
67
77
|
|
@@ -82,7 +92,10 @@ By including `QML::Access`, you can also define **properties and signals** in Ru
|
|
82
92
|
Properties are used to bind data between QML and Ruby.
|
83
93
|
Signals are used to provide the observer pattern-like notification from Ruby to QML.
|
84
94
|
|
95
|
+

|
96
|
+
|
85
97
|
```ruby
|
98
|
+
# Ruby
|
86
99
|
class FizzBuzz
|
87
100
|
include QML::Access
|
88
101
|
register_to_qml under: "Example", version: "1.0"
|
@@ -114,8 +127,7 @@ end
|
|
114
127
|
```
|
115
128
|
|
116
129
|
```qml
|
117
|
-
// main.qml
|
118
|
-
|
130
|
+
// QML - main.qml
|
119
131
|
import QtQuick 2.2
|
120
132
|
import QtQuick.Controls 1.1
|
121
133
|
import QtQuick.Layouts 1.1
|
@@ -196,25 +208,30 @@ To bind list data between QML ListView and Ruby, you can use ListModels.
|
|
196
208
|
|
197
209
|
* `QML::Data::ArrayModel` - provides a simple list model implementation using Array.
|
198
210
|
|
211
|
+
* `QML::Data::QueryModel` - for databases (like ActiveRecord, Sequel or something)
|
212
|
+
|
199
213
|
This example uses `ArrayModel` to provide list data for a QML ListView.
|
200
214
|
When the content of the ArrayModel is changed, the list view is also automatically updated.
|
201
215
|
|
202
|
-
|
203
|
-
class TodoModel < QML::Data::ArrayModel
|
204
|
-
column :title, :description, :due_date
|
205
|
-
end
|
216
|
+
#### Examples
|
206
217
|
|
218
|
+
* [Todo example](https://github.com/seanchas116/ruby-qml/tree/master/examples/todo_sequel)
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
# Ruby
|
207
222
|
class TodoController
|
208
223
|
include QML::Access
|
209
224
|
register_to_qml under: "Example", version: "1.0"
|
210
225
|
|
211
|
-
property :model,
|
226
|
+
property :model, QML::Data::ArrayModel.new(:title, :description, :due_date)
|
212
227
|
|
213
228
|
def add(title, description, due_date)
|
214
|
-
|
229
|
+
# Items of list models must be "Hash-like" (have #[] method to get columns)
|
230
|
+
item = {
|
215
231
|
title: title,
|
216
232
|
description: description,
|
217
|
-
due_date: due_date
|
233
|
+
due_date: due_date
|
234
|
+
}
|
218
235
|
p item
|
219
236
|
model << item
|
220
237
|
end
|
@@ -222,6 +239,7 @@ end
|
|
222
239
|
```
|
223
240
|
|
224
241
|
```qml
|
242
|
+
// QML
|
225
243
|
ListView {
|
226
244
|
model: todo.model
|
227
245
|
delegate: Text {
|
@@ -233,6 +251,54 @@ TodoController {
|
|
233
251
|
}
|
234
252
|
```
|
235
253
|
|
254
|
+
### Combile asynchronous operations
|
255
|
+
|
256
|
+
In QML, all UI-related operations are done synchronously in the event loop.
|
257
|
+
To set result of asynchronous operations to the UI, use `QML.later` or `QML::Dispatchable#later`.
|
258
|
+
|
259
|
+
#### Examples
|
260
|
+
|
261
|
+
* [Twitter Example](https://github.com/seanchas116/ruby-qml/tree/master/examples/twitter)
|
262
|
+
|
263
|
+
```ruby
|
264
|
+
# Ruby
|
265
|
+
class HeavyTaskController
|
266
|
+
# QML::Access includes QML::Dispathable
|
267
|
+
include QML::Access
|
268
|
+
register_to_qml under: "Example", version: "1.0"
|
269
|
+
|
270
|
+
property :result, ''
|
271
|
+
|
272
|
+
def set_result(result)
|
273
|
+
self.result = result
|
274
|
+
end
|
275
|
+
|
276
|
+
def start_heavy_task
|
277
|
+
Thread.new do
|
278
|
+
self.later.set_result do_heavy_task() # #set_result is called in the main thread in the next event loop
|
279
|
+
# or
|
280
|
+
QML.later do
|
281
|
+
set_result do_heavy_task()
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
```
|
287
|
+
|
288
|
+
```qml
|
289
|
+
// QML
|
290
|
+
Text {
|
291
|
+
text: controller.result
|
292
|
+
}
|
293
|
+
Button {
|
294
|
+
text: "Start!!"
|
295
|
+
onClicked: controller.start_heavy_task()
|
296
|
+
}
|
297
|
+
HeavyTaskController {
|
298
|
+
id: controller
|
299
|
+
}
|
300
|
+
```
|
301
|
+
|
236
302
|
### Use Qt objects in Ruby
|
237
303
|
|
238
304
|
In ruby-qml, Qt objects (QObject-derived C++ objects and QML objects) can be accessed from Ruby via the meta-object system of Qt.
|
@@ -292,7 +358,7 @@ It enables you to use your Qt C++ codes from Ruby easily.
|
|
292
358
|
|
293
359
|
|
294
360
|
```c++
|
295
|
-
// plugin example
|
361
|
+
// C++ - plugin example
|
296
362
|
class MyPlugin : public QObject
|
297
363
|
{
|
298
364
|
Q_OBJECT
|
@@ -305,6 +371,7 @@ public slots:
|
|
305
371
|
```
|
306
372
|
|
307
373
|
```ruby
|
374
|
+
# Ruby
|
308
375
|
plugin = QML::PluginLoader.new(directory, "myplugin").instance
|
309
376
|
plugin.foo
|
310
377
|
```
|
@@ -322,7 +389,7 @@ All objects created inside QML and objects returned from C++ methods will be *ma
|
|
322
389
|
#### Unmanaged objects
|
323
390
|
|
324
391
|
*Unmanaged* objects are not managed and never garbage collected.
|
325
|
-
Objects that have parents
|
392
|
+
Objects that have parents or that obtained from properties of other Qt objects will be *unmanaged* by default.
|
326
393
|
|
327
394
|
#### Specify management status explicitly
|
328
395
|
|
@@ -336,10 +403,6 @@ obj = plugin.create_object
|
|
336
403
|
obj.prefer_managed false
|
337
404
|
```
|
338
405
|
|
339
|
-
## Examples
|
340
|
-
|
341
|
-
See the `/example` directory.
|
342
|
-
|
343
406
|
## Contributing
|
344
407
|
|
345
408
|
Contributions are welcome. When you are contributing to ruby-qml:
|
data/changes.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# 0.0.2 (2014-07-21)
|
2
|
+
|
3
|
+
* Improve list models
|
4
|
+
|
5
|
+
* Add ArrayModel#replace
|
6
|
+
* Add QueryModel for ORMs
|
7
|
+
* Specify column names in ListModel#initialize
|
8
|
+
|
9
|
+
* Add To-do example with [Sequel](http://sequel.jeremyevans.net/)
|
10
|
+
|
11
|
+
* Bug fixes
|
12
|
+
|
13
|
+
* Improve README
|
14
|
+
|
15
|
+
# 0.0.1 (2014-07-19)
|
16
|
+
|
17
|
+
* Initial release
|
Binary file
|
Binary file
|
@@ -6,10 +6,6 @@ module Examples
|
|
6
6
|
module Todo
|
7
7
|
VERSION = '0.1'
|
8
8
|
|
9
|
-
class TodoModel < QML::Data::ArrayModel
|
10
|
-
column :title, :description, :due_date
|
11
|
-
end
|
12
|
-
|
13
9
|
class TodoController
|
14
10
|
include QML::Access
|
15
11
|
register_to_qml
|
@@ -17,13 +13,14 @@ module Examples
|
|
17
13
|
property :title, ''
|
18
14
|
property :description, ''
|
19
15
|
property :due_date, ''
|
20
|
-
property :model,
|
16
|
+
property :model, QML::Data::ArrayModel.new(:title, :description, :due_date)
|
21
17
|
|
22
18
|
def add
|
23
|
-
item =
|
19
|
+
item = {
|
24
20
|
title: title,
|
25
21
|
description: description,
|
26
|
-
due_date: due_date
|
22
|
+
due_date: due_date
|
23
|
+
}
|
27
24
|
p item
|
28
25
|
model << item
|
29
26
|
end
|
Binary file
|
@@ -0,0 +1,87 @@
|
|
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 with Sequel"
|
9
|
+
|
10
|
+
FontLoader {
|
11
|
+
source: "../assets/fonts/fontawesome-webfont.ttf"
|
12
|
+
}
|
13
|
+
id: window
|
14
|
+
property int margin: 10
|
15
|
+
width: layout.implicitWidth + 2 * margin
|
16
|
+
height: layout.implicitHeight + 2 * margin
|
17
|
+
|
18
|
+
RowLayout {
|
19
|
+
id: layout
|
20
|
+
anchors.fill: parent
|
21
|
+
anchors.margins: window.margin
|
22
|
+
ColumnLayout {
|
23
|
+
TextField {
|
24
|
+
placeholderText: "Title"
|
25
|
+
id: titleField
|
26
|
+
}
|
27
|
+
TextField {
|
28
|
+
placeholderText: "Description"
|
29
|
+
id: descriptionField
|
30
|
+
}
|
31
|
+
Calendar {
|
32
|
+
id: calendar
|
33
|
+
}
|
34
|
+
Button {
|
35
|
+
text: "Add"
|
36
|
+
onClicked: todo.add()
|
37
|
+
}
|
38
|
+
}
|
39
|
+
ColumnLayout {
|
40
|
+
RowLayout {
|
41
|
+
Label { text: "Sort by" }
|
42
|
+
ComboBox {
|
43
|
+
id: orderComboBox
|
44
|
+
model: ListModel {
|
45
|
+
ListElement { text: "Title"; column: "title" }
|
46
|
+
ListElement { text: "Description"; column: "description" }
|
47
|
+
ListElement { text: "Due Date"; column: "due_date" }
|
48
|
+
}
|
49
|
+
property string currentColumn: model.get(currentIndex).column
|
50
|
+
}
|
51
|
+
}
|
52
|
+
ListView {
|
53
|
+
model: todo.model
|
54
|
+
spacing: 10
|
55
|
+
Layout.fillWidth: true
|
56
|
+
Layout.fillHeight: true
|
57
|
+
Layout.alignment: Qt.AlignTop
|
58
|
+
Layout.minimumWidth: 300
|
59
|
+
delegate: ColumnLayout {
|
60
|
+
Text {
|
61
|
+
font.bold: true
|
62
|
+
text: title
|
63
|
+
}
|
64
|
+
Text {
|
65
|
+
text: description
|
66
|
+
}
|
67
|
+
RowLayout {
|
68
|
+
Text {
|
69
|
+
font.family: "FontAwesome"
|
70
|
+
text: "\uf073"
|
71
|
+
}
|
72
|
+
Text {
|
73
|
+
text: Qt.formatDate(due_date)
|
74
|
+
}
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
TodoController {
|
81
|
+
id: todo
|
82
|
+
title: titleField.text
|
83
|
+
description: descriptionField.text
|
84
|
+
due_date: calendar.selectedDate
|
85
|
+
order_by: orderComboBox.currentColumn
|
86
|
+
}
|
87
|
+
}
|
@@ -0,0 +1,66 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__)
|
2
|
+
require 'qml'
|
3
|
+
require 'sequel'
|
4
|
+
|
5
|
+
module Examples
|
6
|
+
module Todo
|
7
|
+
VERSION = '0.1'
|
8
|
+
|
9
|
+
DB = Sequel.sqlite
|
10
|
+
|
11
|
+
DB.create_table :todos do
|
12
|
+
primary_key :id
|
13
|
+
String :title
|
14
|
+
String :description
|
15
|
+
Date :due_date
|
16
|
+
end
|
17
|
+
|
18
|
+
class SequelModel < QML::Data::QueryModel
|
19
|
+
attr_accessor :dataset
|
20
|
+
|
21
|
+
def initialize(dataset)
|
22
|
+
@dataset = dataset
|
23
|
+
super(*dataset.columns)
|
24
|
+
end
|
25
|
+
|
26
|
+
def query_count
|
27
|
+
@dataset.count
|
28
|
+
end
|
29
|
+
|
30
|
+
def query(offset, count)
|
31
|
+
@dataset.offset(offset).limit(count).all
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class TodoController
|
36
|
+
include QML::Access
|
37
|
+
register_to_qml
|
38
|
+
|
39
|
+
def initialize
|
40
|
+
super
|
41
|
+
@todo_dataset = DB[:todos]
|
42
|
+
self.model = SequelModel.new(@todo_dataset)
|
43
|
+
end
|
44
|
+
|
45
|
+
property :title, ''
|
46
|
+
property :description, ''
|
47
|
+
property :due_date, ''
|
48
|
+
property :order_by, ''
|
49
|
+
property :model
|
50
|
+
|
51
|
+
def add
|
52
|
+
@todo_dataset.insert(title: title, description: description, due_date: due_date)
|
53
|
+
model.update
|
54
|
+
end
|
55
|
+
|
56
|
+
on_changed :order_by do
|
57
|
+
model.dataset = @todo_dataset.order(order_by.to_sym)
|
58
|
+
model.update
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
QML.application do |app|
|
65
|
+
app.load_path Pathname(__FILE__) + '../main.qml'
|
66
|
+
end
|
Binary file
|
data/examples/twitter/main.qml
CHANGED
@@ -5,32 +5,44 @@ import Examples.Twitter 0.1
|
|
5
5
|
|
6
6
|
ApplicationWindow {
|
7
7
|
visible: true
|
8
|
-
width:
|
9
|
-
height:
|
10
|
-
title: "Twitter Test"
|
8
|
+
width: 300
|
9
|
+
height: 500
|
10
|
+
title: "Twitter Search Test - " + controller.word
|
11
11
|
|
12
|
-
|
12
|
+
ColumnLayout {
|
13
13
|
anchors.fill: parent
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
14
|
+
anchors.margins: 10
|
15
|
+
TextField {
|
16
|
+
id: wordField
|
17
|
+
placeholderText: 'Search...'
|
18
|
+
onEditingFinished: controller.fetch_tweets()
|
19
|
+
}
|
20
|
+
ScrollView {
|
21
|
+
Layout.fillHeight: true
|
22
|
+
Layout.fillWidth: true
|
23
|
+
ListView {
|
24
|
+
model: controller.model
|
25
|
+
delegate: RowLayout {
|
26
|
+
Image {
|
27
|
+
width: 100
|
28
|
+
height: 100
|
29
|
+
source: user_icon
|
30
|
+
}
|
31
|
+
ColumnLayout {
|
32
|
+
Text {
|
33
|
+
font.bold: true
|
34
|
+
text: user_name
|
35
|
+
}
|
36
|
+
Text {
|
37
|
+
text: tweet_text
|
38
|
+
}
|
39
|
+
}
|
28
40
|
}
|
29
41
|
}
|
30
42
|
}
|
31
43
|
}
|
32
|
-
|
33
44
|
TwitterController {
|
34
45
|
id: controller
|
46
|
+
word: wordField.text
|
35
47
|
}
|
36
48
|
}
|