qtqml

How to override a function, but call the base-object's version with no object id


I'm sure that you can do this, but I can't find how.

I need to override the open() method in a Popup-derived object in order to pass it a parameter. Here is a minimized sample of main.qml:

// main.qml
    import QtQuick 2.15
    import QtQuick.Window 2.15
    import QtQuick.Controls 2.5
    
    Window {
        width: 640
        height: 480
        visible: true
        title: "Call a base-object's function in an override"
    
        MyPopup {
            id: mypopup
            anchors.centerIn: parent
        }
    
        Button {
            text: "Say hi."
            onClicked: mypopup.open("hi")
        }
    }

And here is my new object, derived from Popup:

// MyPopup.qml
import QtQuick 2.0
import QtQuick.Controls 2.5

Popup {
    Text {
        id: greeting
        text: "bye"
    }

    function open( newText ) {
        greeting.text = newText
        Popup.open()                  <-- This is what I can't figure out
    }
}

If the base object had an id, then I would use it here, but the base class, Popup, is not instantiated. So how would I access its version of open()?

When I tried Popup.open(), as above, I was met with the error:

qrc:/MyPopup.qml:12: TypeError: Property 'open' of object [object Object] is not a function

When I tried Popup:open(), I got:

qrc:/MyPopup.qml:0: RangeError: Maximum call stack size exceeded.

which means the derived version of open() was calling itself.

So how do I call Popup's version of open()?


Solution

  • QML does not allow to override functions, it can only be customized by changing or creating properties and creating new functions.

    On the other hand the ids have a scope so it is valid to set ids in the components and these will have meaning in the component.

    In your case there are the following possible solutions:

    1. Create a new function:

    MyPopup.qml

    import QtQuick 2.0
    import QtQuick.Controls 2.5
    
    Popup {
        id: root
        property alias text: greeting.text
        Text {
            id: greeting
            text: "bye"
        }
        function foo(newText){
            greeting.text = newText
            root.open()
        }
    }
    

    main.qml

    // ...
    onClicked: mypopup.foo("hi")
    // ...
    
    1. Expose the text as a new property (such as via an alias)

    MyPopup.qml

    import QtQuick 2.0
    import QtQuick.Controls 2.5
    
    Popup {
        id: root
        property alias text: greeting.text
        Text {
            id: greeting
            text: "bye"
        }
    }
    

    main.qml

    // ...
    Button {
        text: "Say hi."
        onClicked: {
            mypopup.text = "hi"
            mypopup.open()
        }
    }
    // ...