qml 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/README.md +82 -19
  4. data/changes.md +17 -0
  5. data/examples/fizzbuzz/capture.png +0 -0
  6. data/examples/todo_array/capture.png +0 -0
  7. data/examples/{todo → todo_array}/main.qml +1 -1
  8. data/examples/{todo/todo.rb → todo_array/todo_array.rb} +4 -7
  9. data/examples/todo_sequel/capture.png +0 -0
  10. data/examples/todo_sequel/main.qml +87 -0
  11. data/examples/todo_sequel/todo_sequel.rb +66 -0
  12. data/examples/twitter/capture.png +0 -0
  13. data/examples/twitter/main.qml +31 -19
  14. data/examples/twitter/twitter.rb +46 -23
  15. data/ext/qml/accessclass.cpp +1 -3
  16. data/ext/qml/ext_anywrapper.cpp +36 -0
  17. data/ext/qml/ext_anywrapper.h +26 -0
  18. data/ext/qml/ext_metaobject.cpp +3 -1
  19. data/ext/qml/init.cpp +3 -3
  20. data/ext/qml/listmodel.cpp +29 -4
  21. data/ext/qml/listmodel.h +2 -0
  22. data/ext/qml/util.cpp +7 -0
  23. data/ext/qml/util.h +1 -0
  24. data/ext/qml/weakvaluereference.cpp +34 -9
  25. data/ext/qml/weakvaluereference.h +7 -5
  26. data/lib/qml/class_builder.rb +1 -0
  27. data/lib/qml/data.rb +1 -0
  28. data/lib/qml/data/array_model.rb +23 -2
  29. data/lib/qml/data/list_model.rb +26 -26
  30. data/lib/qml/data/query_model.rb +60 -0
  31. data/lib/qml/version.rb +1 -1
  32. data/qml.gemspec +5 -1
  33. data/spec/qml/data/array_model_spec.rb +43 -56
  34. data/spec/qml/data/list_model_spec.rb +17 -0
  35. data/spec/qml/data/query_model_spec.rb +62 -0
  36. data/spec/shared_examples/qml/data/list_model.rb +33 -0
  37. data/spec/spec_helper.rb +7 -0
  38. metadata +70 -30
  39. data/ext/qml/ext_gcmarker.cpp +0 -39
  40. data/ext/qml/ext_gcmarker.h +0 -27
  41. data/spec/qml/.access_spec.rb.swp +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0dd71ef4746849334db1b91614801963b036e5f9
4
- data.tar.gz: 364c1f9e5d2fd15f937dd5ab009982160fdcd121
3
+ metadata.gz: 31d0f1bbab5b1fa3d4b602baa55fc7df071f65a4
4
+ data.tar.gz: 4ba0b8cecc4f63b26f2284e56f132d19bd176c2b
5
5
  SHA512:
6
- metadata.gz: 6843d7ff307be7803b1748943a7cd83ee0a84e29016e9714fbb4545ed4759e94b664c27ac9956deff501823ac9c1f24af768c977833ee91dd8d89b2ec419e58b
7
- data.tar.gz: 6eca2b5f9227c63241d1066053d922a9b5309b530476eeb780caa7a2e37be609a004fcb374ddbce3238846d4d03115f405cd1b9574487ea3803cc9e791b78979
6
+ metadata.gz: 29d4ae1d6ff4f3218cea47dd8d40b0b02441beb1a82f678138618c654dcc9ac0bf71f5cac6c11717ae13a6dc6d43cc1fab7fce3d061b01efe6761a308cba8c10
7
+ data.tar.gz: cb4a008e7083492d416a09d472668f67dc751db63ffd7d31d97d72726e9ec21610d4562e638c410548aaddedda3a1f2bc533bb2b0e7e021f4b9d77ec01e23ff1
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in qml.gemspec
4
4
  gemspec name: "qml"
5
+
6
+ gem 'coveralls', require: false
data/README.md CHANGED
@@ -1,14 +1,25 @@
1
1
  # ruby-qml
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/qml.svg)](http://badge.fury.io/rb/qml)
3
4
  [![Build Status](https://travis-ci.org/seanchas116/ruby-qml.svg?branch=master)](https://travis-ci.org/seanchas116/ruby-qml)
4
-
5
- **NOTE: ruby-qml is not yet released as a gem.**
5
+ [![Coverage Status](https://coveralls.io/repos/seanchas116/ruby-qml/badge.png?branch=master)](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
+ [![Screenshot](https://raw.github.com/seanchas116/ruby-qml/master/examples/todo_sequel/capture.png)](https://github.com/seanchas116/ruby-qml/tree/master/examples/todo_sequel)
16
+
17
+ [![Screenshot](https://raw.github.com/seanchas116/ruby-qml/master/examples/twitter/capture.png)](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
+ ![Screenshot](https://raw.github.com/seanchas116/ruby-qml/master/examples/fizzbuzz/capture.png)
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
- ```ruby
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, TodoModel.new
226
+ property :model, QML::Data::ArrayModel.new(:title, :description, :due_date)
212
227
 
213
228
  def add(title, description, due_date)
214
- item = OpenStruct.new(
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 and that obtained from properties of other Qt objects will be *unmanaged* by default.
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:
@@ -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
@@ -55,7 +55,7 @@ ApplicationWindow {
55
55
  text: "\uf073"
56
56
  }
57
57
  Text {
58
- text: due_date
58
+ text: Qt.formatDateTime(due_date)
59
59
  }
60
60
  }
61
61
  }
@@ -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, TodoModel.new
16
+ property :model, QML::Data::ArrayModel.new(:title, :description, :due_date)
21
17
 
22
18
  def add
23
- item = OpenStruct.new(
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
@@ -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
@@ -5,32 +5,44 @@ import Examples.Twitter 0.1
5
5
 
6
6
  ApplicationWindow {
7
7
  visible: true
8
- width: 200
9
- height: 100
10
- title: "Twitter Test"
8
+ width: 300
9
+ height: 500
10
+ title: "Twitter Search Test - " + controller.word
11
11
 
12
- ListView {
12
+ ColumnLayout {
13
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
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
  }