[SOLVED] Using QSettings from QML



  • Hello
    I'm new to the forum and pretty new to QT5 development with QML as well.
    I've got an application using some C++ objects and QML for the GUI.
    I'm tryng to store values in a .conf file using QSettings.
    I am creating a settings object my main object:
    @
    application.h:
    #include <QSettings>

    class RS232VisualizerMain : public QObject
    {
    Q_OBJECT
    private:

    SerialConnect* serialPort;
    QSettings* appSettings;
    

    }

    application.cpp:
    RS232VisualizerMain::RS232VisualizerMain(QObject *parent) :
    QObject(parent)
    {
    appSettings = new QSettings;
    appSettings->setValue("main/test","test");
    }
    @

    I can save values from my C-class using the code above.
    However, I couldn't figure out how to write settings from the QML code. I'm trying to set the object as a context property and writing to it from qml:
    @
    application.cpp:
    engine = new QQmlEngine;

    //export context properties to qml
    

    engine->rootContext()->setContextProperty("appSettings",appSettings);

    component = new QQmlComponent(engine);
    component->loadUrl(QUrl("qrc:/qml/main.qml"));
    if ( !component->isReady() ) {
        qWarning("%s", qPrintable(component->errorString()));
        return 1;
    }
    topLevel = component->create();
    window = qobject_cast<QQuickWindow *>(topLevel);
    if ( !window ) {
        qWarning("Error: Your root item has to be a Window.");
        return 1;
    }
    window->show();
    

    main.qml:
    Component.onCompleted: {
    appSettings.setValue("serialPort/BAUD", "9600")
    }
    @

    With the setValue statement in QML like this, the application crashes on startup with exit code 0

    I'm certainly missing something obvious. Any hint to tutorials, documentation or existing forum threads is appreciated.


  • Moderators

    the QSettings class doesn't have any callable methods out of QML.
    For this they would have defined as SLOTS or with the Q_INVOKABLE macro.
    You can write a wrapper class for your QSettings object which has such callable methods and forwards them to the QSettings instance. Then set this wrapper class as context-property.



  • Thank you for the explanation. It helps me very much to understand what's going on. I've now created a wrapper class, according to the example given in this thread:
    http://qt-project.org/forums/viewthread/11696/#64044

    I can create an object of the wrapper class and also add values from C++. However, my applications still crashes on startup if I'm trying to set a value from QML. This is how my code looks now:
    @
    appSettings.h:
    #ifndef APPSETTINGS_H
    #define APPSETTINGS_H
    #include <QSettings>
    #include <QCoreApplication>

    class appSettings : public QSettings
    {
    Q_OBJECT

    public:
    explicit appSettings(QObject *parent = 0) : QSettings(QSettings::UserScope,
    QCoreApplication::instance()->organizationName(), QCoreApplication::instance()->applicationName(), parent) {}

    Q_INVOKABLE inline void setValue(const QString &key, const QVariant &value) { QSettings::setValue(key, value); }
    Q_INVOKABLE inline QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const { return QSettings::value(key, defaultValue); }
    

    };
    Q_DECLARE_METATYPE(appSettings*)

    #endif // APPSETTINGS_H

    application.cpp:
    staticSettings = new appSettings;
    staticSettings->setValue("serialPort/test", "value");
    @

    The above setValue statement works as intended.
    @
    application.cpp:
    engine = new QQmlEngine;

    //export context properties to qml
    

    engine->rootContext()->setContextProperty("staticSettings",staticSettings);

    component = new QQmlComponent(engine);
    component->loadUrl(QUrl("qrc:/qml/main.qml"));
    if ( !component->isReady() ) {
        qWarning("%s", qPrintable(component->errorString()));
        return 1;
    }
    topLevel = component->create();
    window = qobject_cast<QQuickWindow *>(topLevel);
    if ( !window ) {
        qWarning("Error: Your root item has to be a Window.");
        return 1;
    }
    window->show();
    

    main.qml:
    Component.onCompleted: {
    staticSettings.setValue("serialPort/BAUD", "9600")
    }
    @

    EDIT:
    And it is working like a charm! Thank you very much
    P.S: You should of course create the staticSettings object first and then declare it as context property ;-) I did the two steps in different methods in reverse order and my applicaton crashed.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.