Dynamical theming of QML objects



  • Hi,

    I try to theme a QML app in a dynamic way. For this I have a base component Theme.qml, which is located in the root folder of the application. It defines the default properties.

    @import QtQuick 1.0

    Item
    {
    id: theme

    property string wallpaperFile: ""
    
    property color desktopColor: "#222222"
    
    property Gradient desktopGradient:
    Gradient
    {
    

    id: desktopGradient
    GradientStop { position: 0.00; color: "#73a2ce"; }
    GradientStop { position: 1.00; color: "#80aad0"; }
    }

    property Gradient deskbarGradient:
    Gradient
    {
    

    id: deskbarGradient
    GradientStop { position: 0.00; color: "#d04b4b4b"; }
    GradientStop { position: 0.50; color: "#d0282828"; }
    GradientStop { position: 0.50; color: "#d0000000"; }
    GradientStop { position: 1.00; color: "#d0000000"; }
    }
    }
    @

    In subfolders like e.g. ./Themes/Dark there are located CustomTheme.qml components.

    @
    import QtQuick 1.0
    import "../../"

    Item
    {
    property Theme theme: theme

    Theme
    {
    

    id: theme

    wallpaperFile: "Themes/Wood2/wallpaper.jpg"
    }
    }
    @

    These theme files will be loaded in a Loader from within Application.qml. I choose this approach to avoid a fixed import statement in the Application component (I want to be able to switch the theme while runtime).

    So here are my first 2 questions:

    *1. Is this approach feasible?

    1. I don't like the fact, that theme must be a visible component due to the loader. Is that bad programming behaviour?*

    Here is the code of the Application.qml:

    @
    import QtQuick 1.0

    Item
    {
    /*
    * XXX check correct usage of visible base class Item in this context
    * XXX check possible race conditions from slow loading (ex. network)
    */
    Loader
    {
    id: desktopTheme
    source: "./Themes/Wood2/CustomTheme.qml"
    onLoaded:
    {
    console.log( "theme " + source + " loaded." );
    desktop.theme = desktopTheme.item.theme;
    }
    }

    Desktop
    {
    

    id: desktop
    }

    Component.onCompleted:
    {
    

    console.log( "application ready." );
    }
    }
    @

    Finally the loader sets the property theme (an object instance) which is defined for example in Desktop. Unfortunately this is one reason, why i have to wrap the Theme object in the CustomScene components, because while runtime I get an error when I assign there the CustomTheme instead (different types) ... overloading isn't available here, right? :)

    @
    import QtQuick 1.0

    Item
    {
    id: desktop

    property Theme theme
    
    anchors.fill: parent
    
    ...
    
    Image
    {
    

    id: wallpaper
    anchors.fill: parent
    source: theme.wallpaperFile
    }
    }
    @

    And this leads me to the last question:
    *3. I need to specify the exact image location in the CustomTheme relative to the root folder (am not sure, if this is a disadvantage of the loader approach), because else the image will be searched in the root folder

    Finally again the most important question, because I am still a newbie in QML. Is this approach feasible in any way or will it lead to problems I can't oversee right now?*

    Thank you for your comments!


Log in to reply
 

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