Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

[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