Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QML: Make property readonly in derived class

Tags:

qt

qml

I'm pretty sure the answer is no, but I thought I should ask anyway. Can an inherited property be made readonly/constant in a pure QML derived class?

// Base.qml
Item {
    property int foo: 42
}

// Derived.qml
Base {
    foo: 99 // Make constant somehow!
}

I'm currently tackling this by detecting a change in foo and printing an error to the console, but that's hardly a mark of good API...

I have a menu item class which can represent menu entries, submenus, separators, etc. I need to specialise it's behaviour, but only for when it is in submenu mode. I can change the inheritance tree so I have a subclass for each menu type, but this seems silly as each subclass will only contain a single readonly property. However if there isn't another way, I will have to.

like image 743
cmannett85 Avatar asked Feb 27 '15 16:02

cmannett85


2 Answers

You can also transform foo as a readonly alias to an internal property _foo that you will use only for assignment in the derived class:

// Base.qml
Item {
    id: base

    readonly property alias foo: base._foo

    property int _foo: 42 // only used for assignment in subclasses
}

To be used in another Component:

Item {
    Base {
        id: child0
    }

    Base {
        id: child1
        _foo: 99
    }

    Base {
        id: child2
        _foo: child1.foo
    }

    Component.onCompleted: {
        console.log("child0:", child0.foo,"child1:", child1.foo, "child2:", child2.foo)
        child1.foo = 5 // not allowed!
        console.log("child0:", child0.foo,"child1:", child1.foo, "child2:", child2.foo)
    }
}

Output:

child0: 42 child1: 99 child2: 99
TypeError: Cannot assign to read-only property "foo"

Note: of course it is still possible to modify _foo later. But if you remember to use it only for assignment, then you have the desired behavior with a readonly foo in the derived class.

like image 141
augre Avatar answered Nov 13 '22 23:11

augre


Why not use inherited getter/setters for a private foo? something like :

//Base.qml
Item
{
    QtObject
    {
       id : privateFoo
       property int foo : 42
    }

    function getFoo() {return privateFoo.foo;}
    function setFoo(newFoo) { privateFoo.foo = newFoo; }
}

//derived.qml
Base
{
    function getFoo() {return 99;}
    function setFoo(newFoo) { /*do nothing */ }
}

(I haven't tested this code)

like image 36
Roey Lehman Avatar answered Nov 13 '22 23:11

Roey Lehman