c++qtsingletonqmlqtquick2

Change property of the QML singleton with C++


I'm implementing a simplified Ubuntu Touch-like palette (not per-element one).

There is a GlobalPaletteSetting singleton:

pragma Singleton

import QtQuick 2.5

QtObject {
    property Palette current: NonePalette {}
}

and some palette classes like NonePalette or Dark:

Palette {
    normal: PaletteValues {
        background: "white"
        backgroundText: "black"
        base: "white"
        baseText: "black"
        foreground: "white"
        foregroundText: "black"
        overlay: "white"
        overlayText: "black"
        field: "white"
        fieldText: "black"
        selection: "pink"
    }
}

So, the global palette can be changed in QML:

import "Customization/Palettes/Dark"

//...

DarkPalette {
    id: dark
}

Component.onCompleted: {
    GlobalPaletteSetting.current = dark
}

I want to set the global palette by setting the environment variable. Just like the QtQuick styles are working.

So, an access to GlobalPaletteSetting is needed from C++. And also a method to load QML files with palettes and setting the GlobalPaletteSetting.current.

How to do that?


Solution

  • Here's the code I came up with:

    QQmlComponent component(engine());
    const char *source =
            "import QtQuick 2.0\n"
            "import Components 1.0\n"
            "QtObject {\n"
            "    property var style: CustomStyle\n"
            "    function setColor(c) { CustomStyle.headerColor = c; }\n"
            "}";
    component.setData(source, QUrl());
    QObject *item = component.create();
    QObject *style = qvariant_cast<QObject*>(item->property("style"));
    style->setProperty("headerColor", QColor(255, 0, 0));
    

    Here, CustomStyle is my style definition, a singleton. You can find a complete example at https://github.com/vprus/qt-quick-little-program/tree/style-preinitialization

    The recommendation to use objectName did not work for me - whether I put it at the top level of my singleton component, or in a child item, findChild returns 0. It also does not work on top-level of regular components, only children thereof. You can find my attempt at https://github.com/vprus/qt-quick-little-program/commit/99933d31f03b6dca8e380cc698e53681cd9a54ba

    Regarding your second question, about loading your style definition at runtime, you can adjust the above code - use setData or loadUrl to load component definition, use create to create an instance, and then set the instance. In fact, you can do engine()->rootContext()->setContextProperty("style", ...) so that everything in your QML can access 'style' variable, which might be easier than having a singleton.