In the previous example, we could "use the SQLite offline storage API to store the app's settings". We also show how to store the JSON we need in a local file in the example "How to dynamically modify the data in the Listmodel in the QML application and store it in JSON format". In this article, we will use the localstorage provided by Qtquick to store the data we need.
To illustrate the problem, I'll start by creating a template based on the "QtQuick App with QML UI (qmake)". First we revise our main.cpp as follows:
MAIN.QML
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
# Include <QDebug>
int main (int argc, char *argv[])
{
qguiapplication app (argc, argv);
Qquickview view;
Qdebug () << "Local Storage path:" << view.engine ()->offlinestoragepath ();
Qobject::connect (View.engine (), SIGNAL (Quit ()), Qapp, SLOT (Quit ()));
View.setsource (Qurl (qstringliteral ("qrc:///main.qml"));
View.setresizemode (Qquickview::sizerootobjecttoview);
View.show ();
return app.exec ();
}
When we run our application, we can see:
Local Storage path: "/home/phablet/.local/share/localstorage/qml/offlinestorage"
This path is obviously different from the actual path we produce when we actually run it on the phone:
This also shows that the implementation on Ubuntu is different from the standard QT implementation. From the above we can see that the time path of the database is:
phablet@ubuntu-phablet:~/.local/share/localstorage.liu-xiao-guo/databases$ ls
4ff10001f402923590ceb1d12a0cffc6.ini 4ff10001f402923590ceb1d12a0cffc6.sqlite
To enable the application to exit itself, we have added the following statement:
Qobject::connect (View.engine (), SIGNAL (Quit ()), Qapp, SLOT (Quit ()));
This allows the app to exit when you use Qt.quit () in our QML code. This is different from our general design. We generally do not need to do this. For this application, we would like to get an event at the exit to save our settings, all of which we have such a special treatment.
In order to be able to access the SQLite database, we designed the following Database.js file:
Database.js
.import QtQuick.LocalStorage 2.0 as Sql
var db;
function initDatabase() {
print('initDatabase()')
db = Sql.LocalStorage.openDatabaseSync("CrazyBox", "1.0", "A box who remembers its position", 100000);
db.transaction( function(tx) {
print('... create table')
tx.executeSql('CREATE TABLE IF NOT EXISTS data(name TEXT, value TEXT)');
});
}
function readData() {
print('readData()')
if(!db) { return; }
db.transaction( function(tx) {
print('... read crazy object')
var result = tx.executeSql('select * from data where name="crazy"');
if(result.rows.length === 1) {
print('... update crazy geometry')
// get the value column
var value = result.rows[0].value;
// convert to JS object
var obj = JSON.parse(value)
// apply to object
crazy.x = obj.x;
crazy.y = obj.y;
}
});
}
function storeData() {
print('storeData()')
if(!db) { return; }
db.transaction( function(tx) {
print('... check if a crazy object exists')
var result = tx.executeSql('SELECT * from data where name = "crazy"');
// prepare object to be stored as JSON
var obj = { x: crazy.x, y: crazy.y };
if(result.rows.length === 1) {// use update
print('... crazy exists, update it')
result = tx.executeSql('UPDATE data set value=? where name="crazy"', [JSON.stringify(obj)]);
} else { // use insert
print('... crazy does not exists, create it')
result = tx.executeSql('INSERT INTO data VALUES (?,?)', ['crazy', JSON.stringify(obj)]);
}
});
}
Here, we can create a database called "Crazybox" and produce a table in it called data. We can update the data to the table. From this example, we can see that this method is used to store our JSON data without using the C + + code (the reference routine "how to dynamically modify the data in the Listmodel in the QML application and store it in JSON format"). This is good news for most developers who are not very familiar with C + + code.
MAIN.QML
import QtQuick 2.0
import Ubuntu.Components 1.1
import "database.js" as DB
/*!
\brief MainView with a Label and Button elements.
*/
MainView {
// objectName for functional testing purposes (autopilot-qt5)
objectName: "mainView"
// Note! applicationName needs to match the "name" field of the click manifest
applicationName: "localstorage.liu-xiao-guo"
/*
This property enables the application to change orientation
when the device is rotated. The default is false.
*/
//automaticOrientation: true
// Removes the old toolbar and enables new features of the new header.
useDeprecatedToolbar: false
width: units.gu(60)
height: units.gu(85)
Page {
title: i18n.tr("Localstorage")
Rectangle {
id: crazy
objectName: 'crazy'
width: 200
height: 200
x: 50
y: 50
color: "#53d769"
border.color: Qt.lighter(color, 1.1)
Text {
anchors.centerIn: parent
text: Math.round(parent.x) + '/' + Math.round(parent.y)
}
MouseArea {
anchors.fill: parent
drag.target: parent
}
}
Component.onCompleted: {
DB.initDatabase();
print("it is going to read data");
DB.readData();
}
Component.onDestruction: {
print("it is going to save data");
DB.storeData();
}
Button {
anchors.bottom: parent.bottom
anchors.bottomMargin: units.gu(1)
anchors.horizontalCenter: parent.horizontalCenter
text: "Close"
onClicked: {
Qt.quit();
}
}
}
}
Our MAIN.QML design is very simple. After the UI is loaded, we initialize the database and read the data that has been stored. If the data already exists, read it out and initialize our rectangle "crazy". When the app exits, we store our data. It should be noted that when we use our fingers to drag and drop the app, our app does not accept the following events:
Component.ondestruction: {
print ("It is going to save data");
Db.storedata ();
}
We have to get this event by selecting the "Quit" button.
To run our application:
Whenever we exit the app and restart the app, we can see that our green squares are in the same position as the last time we exited.
The source code of the whole project is: https://github.com/liu-xiao-guo/localstorage