[Development] Serialising UI state in QML via QSettings and JSON: QByteArray vs QString

Mitch Curtis mitch.curtis at qt.io
Mon Oct 29 17:42:36 CET 2018


Hi.

I'm trying to sort out some way of saving SplitView's (Qt Quick Controls 2) state. The goals that I have are:

#1 Allow SplitView's state to easily be saved to QSettings. That's covered by the patch in its current form.
#2 Allow SplitView's state to easily be saved to a custom project file, so that applications that need to save UI state on a per-project basis can do so.

Both of these should be doable in QML (besides the IO-related details of saving to a custom project file).

So far, my patch bases its API on that of QMainWindow. Here's the usage documentation showing how it's currently done in QML:

https://codereview.qt-project.org/gitweb?p=qt/qtquickcontrols2.git;a=blob;f=src/quicktemplates2/qquicksplitview.cpp;h=6c5f72b1952e58f3f9c956ac129fc221a3017cb4;hb=4cdc2942c69a15484a65d7c8a48b1f129d7bd3d0#l194

Here's the implementation:

https://codereview.qt-project.org/gitweb?p=qt/qtquickcontrols2.git;a=blob;f=src/quicktemplates2/qquicksplitview.cpp;h=6c5f72b1952e58f3f9c956ac129fc221a3017cb4;hb=4cdc2942c69a15484a65d7c8a48b1f129d7bd3d0#l1143

Here's what QMainWindow does:

http://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/widgets/qmainwindow.cpp?h=dev&id=00b2e45a97205975ee91aa43f00e3dbef1a8907b#n1240

To solve #2, I first tried simply saving a QVariant containing a QByteArray (the contents of which were QDataStream's output). This didn't work because Qt's JSON implementation doesn't support QByteArray; it only supports QString. That is, calling QJsonObject::fromVariantMap(map) where "map" contains a QVariant containing a QByteArray will result in the corresponding JSON value being invalid/null.

I thought that I could get around this by using Qt.atob() and Qt.btoa() in QML to convert the byte array into a Base64 QString, but it turns out that those functions expect a string:

http://code.qt.io/cgit/qt/qtdeclarative.git/tree/src/qml/qml/v8/qqmlbuiltinfunctions.cpp?h=5.12&id=475c74a9926efcd968572563e678988e53804603#n996

Running the attached project gives the following output:

    created QString from SplitView state: QVariant(QByteArray, "\x00\x00\x00{\x01")
    qml: Saved state in QML as QVariant(QByteArray):
    qml: Converted state in QML to a Base64 string:
    expected base64 string in a QVariant, got: QVariant(QString, "")
    qml: Converted state in QML from Base64 string to QVariant(QByteArray):
    in C++, state from QML is: QVariant(QString, "")
    read i as 0 and b as false

So now I'm considering what I should do. I'm thinking about making SplitView convert the QByteArray it creates with QDataStream into a Base64 QString and returning that instead. That can still be saved in QSettings, and can easily be used by both Qt's JSON implementation and Qt.atob() and Qt.btoa(). However, I understand that Base64 encoding can result in slightly larger strings when used on small input (which SplitView's serialisable state will typically be).

With these uncertainties, I thought I'd ask what others think of my proposed approach, and if there are any better ways to solve this.

Cheers.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: splitview-state.zip
Type: application/x-zip-compressed
Size: 2891 bytes
Desc: splitview-state.zip
URL: <http://lists.qt-project.org/pipermail/development/attachments/20181029/f9bc2a03/attachment.bin>


More information about the Development mailing list