File: u1db-qt-example-5.qdoc

package info (click to toggle)
u1db-qt 0.1.8-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 688 kB
  • sloc: cpp: 2,089; python: 60; sql: 40; makefile: 19; sh: 14; xml: 14
file content (386 lines) | stat: -rw-r--r-- 13,753 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
/*!

\page  u1db-qt-tutorial-5.html

\title U1Db-Qt Index Tutorial

This tutorial is designed to demonstrate a variety of essential U1Db-Qt functionality and usage, including:

\list 1
    \li Utilizing the U1db-Qt Index element
    \li Various approaches to define U1db-Qt Document elements when using the Index element
    \li Partnering the U1db-Qt Index element and a QML ListView element 
\endlist

\section1 Storing Data

\section2 The Database Element

\section3 Creating a Database

A Database is very simple to create. It only needs an id and a path where the file will be created. A Database is a model, which can be used by elements, such as the ListView further in this example.

\code
U1db.Database {
    id: aDatabase
    path: "aDatabase4"
}
\endcode

\section1 The Document Element

\section2 Declaring Documents (at Runtime)

A Document can be instantiated at runtime, or generated dynamically. The examples below demonstrate the former.

A very basic Document could include its unique 'id' and 'docId' properties. While it is not mandatory to define these properties, in some cases they can be convenient references. More advanced applications would likely find these very useful, and in some cases may be an absolute necessity to achieve the objectives of the program.

This example of a very simple Document will not initially do anything, until more properties are added and defined:

\code
U1db.Document {
    id: aDocument1
    docId: 'helloworld1'
}
\endcode

A basic but still practical Document definition contains several essential properties. In addition to 'id' and 'docId' (discussed above), the 'database', 'create', and 'defaults' properties are also very important, and are introduced below.

The 'database' property ensures that the Document is attached to an already defined (or possibly soon to be defined one) identified by its id (in this case 'aDatabase'). For example:

\code
U1db.Document {
    id: aDocument1
    database: aDatabase
    docId: 'helloworld1'
}
\endcode

Should the Database not already contain a Document with the same docId ('hellowworld1' in this example) when a 'create' property is present and set to true it will be generated. For example:

\code
U1db.Document {
    id: aDocument1
    database: aDatabase
    docId: 'helloworld1'
    create: true
}
\endcode

However, the Document still requires some data to be useful, which is what the 'defaults' property provides. The value of 'defaults' is a map of data that will be stored in the database (again when the create property is et to true). It contain key:value pairs, where the value can be a string, number, or nested object (e.g. additional fields, lists). For example:

\code
U1db.Document {
    id: aDocument1
    database: aDatabase
    docId: 'helloworld1'
    create: true
    defaults:{"hello": { "world": { "message":"Hello World", "id": 1 } } }
}
\endcode

As mentioned above, lists can also be nested in Document data. Lists provide a convenient method for producing multiple instances of the same key (AKA 'field' or 'sub-field'). The example code below shows valid use of the 'message' and 'id' sub-fields multiple times within the same object.

\code
U1db.Document {
    id: aDocument2
    database: aDatabase
    docId: 'helloworld2'
    create: true
    defaults:{"hello": { "world": [
                            { "message":"Hello World", "id": 2 },
                            { "message":"Hello World", "id": 2.5 }
                        ] } }
}
\endcode

When the default Javascript Object Notation itself is formatted with appropriate line breaks and indentation, it becomes easier to visualize an embedded list, containing sub-fields 'message' and 'id' (and their respective values):

\code
{"hello":
    { "world":
        [
            { "message":"Hello World", "id": 2 },
            { "message":"Hello World", "id": 2.5 }
        ]
    }
}
\endcode

In dot notation these sub-fields are represented by 'hello.world.message' and 'hello.world.id' respectively. Later in this tutorial these will be utilized within the 'expression' property of U1Db-Qt's Index element, in close collaboration with a QML ListView's delegates.


Normally when a docId already exists in a database, and when the set flag is set to true, the value in 'defaults' will be ignored (and the existing data in the database will remain untouched). Sometimes a developer needs to easily overwrite the data in an existing document. The 'contents' property can be used for just that purpose. When 'contents' is defined, its value will replace existing data in the database, for the document identified by the docId. In addition, 'contents' can be used to add new documents, in the same way as the 'create: true' + 'defaults' combination does; in other words, if the document defined by 'docId' does not exist it will be created.

\code
U1db.Document {
    id: aDocument3
    database: aDatabase
    docId: 'helloworld3'
    contents:{"hello": { "world": [
                            { "message":"Hello World", "id": 3 },
                            { "message":"Hello World", "id": 3.33 },
                            { "message":"Hello World", "id": 3.66 }
                        ] } }
}
\endcode

If 'defaults' exists, 'create' is set to 'true' (or 'false' for that matter) and 'contents' is also defined, it is the latter that takes precidence. In other words, 'create' and 'defaults' will be ignored. The following example demonstrates this scenario:

\code
U1db.Document {
    id: aDocument3
    database: aDatabase
    docId: 'helloworld3'
    create: true
    default:{"hello": { "world": [{ "message":"Hello World", "id": 3 }] } }
    contents:{"hello": { "world": [
                                    { "message":"Hello World", "id": 3 },
                                    { "message":"Hello World", "id": 3.33 },
                                    { "message":"Hello World", "id": 3.66 }
                        ] } }
}
\endcode

This snippet simply represents the absence of the 'create' property, which is synonymous with 'create: false'. The Document can still be recognized within the application, but until applicable properties (such as those outlined above) are added and/or modified then nothing will be added or modified in the database, and this instance may have very little practical value.

\code
U1db.Document {
    id: aDocument4
    database: aDatabase
    docId: 'helloworld4'
    defaults:{"hello": { "world": { "message":"Hello World", "id": 4 } } }
}
\endcode

\section3 Samples of Stored Documents

The data stored in the database after defining the above Document elements (and then running the application, will consist of the following:

\table
\header
    \li docId
    \li content
\row

    \li 'helloworld1'
    \li
\code
{
    "hello": {
        "world": {
            "id": 1,
            "message": "Hello World"
        }
    }
}

\endcode


\row

    \li 'helloworld2'
    \li
\code
{
    "hello": {
        "world": [
            {
                "id": 2,
                "message": "Hello World"
            },
            {
                "id": 2.5,
                "message": "Hello World"
            }
        ]
    }
}
\endcode

\row

    \li 'helloworld3'
    \li
\code
{
    "hello": {
        "world": [
            {
                "id": 3,
                "message": "Hello World"
            },
            {
                "id": 3.33,
                "message": "Hello World"
            },
            {
                "id": 3.66,
                "message": "Hello World"
            }
        ]
    }
}
\endcode


\endtable

\section1 Retrieving Data

To retrieve the Documents that were declared earlier requires two additional elements: Index and Query.

\section2 The Index Element

\section3 Creating and Index Element

The Index element requires both a unique 'id' and a pointer to a 'database' in order to begin becoming useful, as demonstrated here:

\code
U1db.Index{
    database: aDatabase
    id: by_helloworld
}
\endcode

In the future, the Index element will support on disk storage of appropriate results / data. At the present time only in memory indexing is done, but once the storing capability is implemented, defining and identifying it is as simple as using the 'name' property (which will be stored in the database along with the relvent data that goes with it). The snippet below shows the use of the 'name' property:

\code
U1db.Index{
    database: aDatabase
    id: by_helloworld
    //name: "by-helloworld"
}
\endcode

The Index element describes, using dot notation, the fields and sub-fields where the developer expects to find information. That information is defined in a list, and added as the value for the 'expression' property. The list can contain one or more entries, as exemplified here (the property is commented out due to its current status):

\code
U1db.Index{
    database: aDatabase
    id: by_helloworld
    //name: "by-helloworld"
    expression: ["hello.world.id","hello.world.message"]
}
\endcode

\section2 The QueryElement

\section3 Creating a Query Element

The Query element has two responsibilities: a bridge from Database+Index to other parts of the application, as well as further filtering of data in the database (in addition to what Index provides).

In order to fulfil its duties as a bridge to an Index (and Database), the 'index' property must point to an Index element, identified by its 'id'. For example:

\code
U1db.Query{
    id: aQuery
    index: by_helloworld
}
\endcode

While Index helps to filter data based on 'where' it is located (e.g. field.sub-field), Query helps determine the additional set of criteria for 'what' is being searched for. The intent of the 'query' property is to provide the mechanism for defnining the search criteria, but at the time of writing that functionality is not yet available. However, once the implementation is in place, using it is only requires defining the property's value (e.g. "Hello World"). Wild card searches using '*' are supported, which is the default query (i.e. if 'query' is not set it is assumed to be '*'). For example (the property is commented out due to its current status):

\code
U1db.Query{
    id: aQuery
    index: by_helloworld
    //query: "*"
}
\endcode

When the 'query' property becomes available, only wildcard search definitions for "starts with" will be suppoprted. Thus the following would be supported:

\code
U1db.Query{
    id: aQuery
    index: by_helloworld
    //query: "Hello*"
}
\endcode


But this would not:

\code
U1db.Query{
    id: aQuery
    index: by_helloworld
    //query: "*World"
}
\endcode

Note: again, the 'query' property is commented out in the above two snippets due to its current status

\section1 Using Data

\section2 Data and the Application UI

\section3 Using Data With Models and Views

This simple snippet represents how to attach a ListModel to a ListView. In this instance the model 'aQuery' is representative of the Query + Index combination defined earlier:

\code
ListView {
    width: units.gu(45)
    height: units.gu(80)
    model: aQuery
}
\endcode

\section4 Data and Delegates

How a model and ListView + delegates work together is a common QML concept, and not specific to U1Db-Qt. However, the asynchronous nature of this relationship is important to understand. When using QML ListView, delegates will be created based on particular properties such as the size of the application window, ListView, and delegate itself (amongst other factors). Each delegate can then represent a Document retrieved from the Database based on the record's index. This example demonstrates some of the property definitions that contribute to determining the number of delegates a ListView will contain:

\code
ListView {
    width: units.gu(45)
    height: units.gu(80)
    model: aQuery

    delegate: Text {
        x: 66; y: 77
    }

}
\endcode


When the number of Documents is less than or equal to the number of delegates then there is a one to one mapping of index to delegate (e.g. the first delegate will represent the Document with an index = 0; the second, index = 1; and so on).

When there are more Documents than delegates the ListView will request a new index depending on the situation (e.g. a user scrolls up or down). For example, if a ListView has 10 delegates, but 32 Documents to handle, when a user initially scrolls the first delegate will change from representing the Document with index = 0 to the Document that might have index = 8; the second, from index = 1 to index = 9; ...; the 10th delegate from index = 9 to index = 17. A second scrolling gesture the first index may change to 15, and the final index 24. And so on. Scrolling in the opposite direction will have a similar effect, but the Document index numbers for each delegate will obviously start to decline (towards their original values).

The following snippet, which modifies the above delegate definition, could demonstrate this effect if there were enough Documents to do so (i.e. some number greater than the number of delegates):

\code
ListView {
    width: units.gu(45)
    height: units.gu(80)
    model: aQuery

    delegate: Text {
        x: 66; y: 77
        text: index
    }

}
\endcode

The object called 'contents' contains one or more properties. This example demonstrates the retrieval of data based on the U1db.Index defined earlier (id: by-helloworld). In this instance the Index contained two expressions simultaniously, "hello.world.id" and "hello.world.message"

\code
ListView {
    width: units.gu(45)
    height: units.gu(80)
    model: aQuery

    delegate: Text {
        x: 66; y: 77
        text: "(" + index + ") '" + contents.message + " " + contents.id + "'"
    }

}
\endcode

*/