After explaining how to use U1DB to store simple bits of information in Ubuntu SDK apps, and saying that that caters for 80% of my need for data storage, I should explain the other thing I do, which is to store dynamic data; documents created from user data.
To understand more about how to retrieve data from U1DB through Indexes and Queries, you can read the core U1DB documentation. Its code examples are for the Python implementation, and QML works differently for creating documents (as we’ve seen, QML is declarative; there’s no code to write, you just describe a document and it all works), but indexing and querying documents have the same underlying philosophy regardless of implementation, and the core docs explain what an index is, what a query is, and how they work.
First, a simple code example.
import QtQuick 2.0
import Ubuntu.Components 0.1
import U1db 1.0 as U1db
import Ubuntu.Components.ListItems 0.1 as ListItem
MainView {
width: units.gu(40)
height: units.gu(71)
/* ----------------------------------------------------
Set up the U1DB database
Declare a named document
---------------------------------------------------- */
U1db.Database { id: db; path: "simpleu1dbdemo2.u1db" }
U1db.Index {
database: db
id: by_type
/* You have to specify in the index all fields you want to retrieve
The query should return the whole document, not just indexed fields
https://bugs.launchpad.net/u1db-qt/+bug/1271973 */
expression: ["things.type", "things.placename"]
}
U1db.Query {
id: places
index: by_type
query: ["*", "*"]
}
Page {
title: "U1DB ListModel"
Column {
id: col
width: parent.width
spacing: units.gu(1)
Label {
width: parent.width
text: "Enter a place to add to list"
horizontalAlignment: Text.AlignHCenter
}
Rectangle {
id: ta
width: parent.width - units.gu(2)
color: "white"
height: inp.height * 2
anchors.horizontalCenter: parent.horizontalCenter
radius: 5
TextInput {
id: inp
width: parent.width - units.gu(2)
anchors.centerIn: parent
onAccepted: inp.adddoc()
function adddoc() {
/* Indexes do not work on top-level fields. So put everything
in the document in a dict called "things" so that they're
not top-level fields any more.
https://bugs.launchpad.net/u1db-qt/+bug/1271972 */
db.putDoc({things: {type: "place", placename: inp.text}})
inp.text = ""
}
}
}
Button {
text: "Add"
width: ta.width
anchors.horizontalCenter: parent.horizontalCenter
onClicked: inp.adddoc()
}
}
ListView {
anchors.top: col.bottom
anchors.bottom: parent.bottom
width: parent.width
model: places
clip: true
delegate: ListItem.Standard {
text: model.contents.placename
control: Button {
text: "x"
width: units.gu(4)
onClicked: {
/* To delete a document, you currently have to set its
contents to empty string. There will be db.delete_doc
eventually.
https://bugs.launchpad.net/u1db-qt/+bug/1243395 */
db.putDoc("", model.docId);
}
}
}
}
}
}
You type in a place name and say “Add”; it gets added to the list. The list is stored in U1DB, so it persists; close the app and open it again and you still have your place names. Click a place to delete it.
This covers almost all the remaining stuff that I need to do with data storage. There are a few outstanding bugs still with using U1DB from QML, which I’ve annotated in the source above, and at the moment you have to work around those bugs by doing things that you ought not to have to; once they’re fixed, this becomes more intuitive to use.