In the previous example, we could “use the SQLite Offline Storage API to store the Settings of the application”. We also showed how to store the JSON we needed in a local file in the routine “How to Dynamically modify the data in the ListModel in QML Applications and store it as JSON.” In this article, we will use LocalStorage provided by QtQuick to store the data we need.

\

To illustrate, I’ll start by creating a template based on “QtQuick App with QML UI (Qmake)”. First we modify 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();
}
Copy the code

\

When we run our application, we can see:

\

Local storage path:  "/home/phablet/.local/share/localstorage/QML/OfflineStorage"
Copy the code

This path is obviously different from the actual path generated when we run it on the phone:

\

\

\

This also shows that the implementation on Ubuntu is still different from the implementation on standard Qt. 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
Copy the code

\

\

To enable the application to exit by itself, we added the following statement:

\

  QObject::connect(view.engine(), SIGNAL(quit()), qApp, SLOT(quit()));
Copy the code

\

This allows the application to exit when we use Qt.quit() in our QML code. This is different from our usual design. We usually don’t need to do that. For this application, we want to get an event to save our Settings on exit, so we have such a special handle.

\

\

To enable access to 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. The 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)]); }}); }Copy the code

Here, we can create a database called “CrazyBox” and produce a table called Data in it. We can update the table. From this example, we can see that we use this method to store our JSON data without using C++ code (see the routine “how to dynamically modify the ListModel data in a QML application and store it as JSON”). This is good news for most developers who are unfamiliar 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(); }}}}Copy the code


\

Our main.qml design is very simple. After the UI is loaded, we initialize the database and read the stored data. If the data already exists, read it and initialize our Rectangle “crazy”. When the application exits, we store our data. It should be noted here that when we drag to close the app with our finger, our app does not receive the following events:

\

        Component.onDestruction: {
            print("it is going to save data");
            DB.storeData();
        }
Copy the code

We must get this event by selecting the “Quit” button.

\

To run our app:

\

   \

\

\

Every time we exit the application and restart it, we can see that our green square is in the same position as the last time we quit.

\

The entire project source at: github.com/liu-xiao-gu…

\