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

Call base object method from QML



  • Hello all! I have the following situation: I use FileDialog from Qt.labs.platform 1.1 and pass FileDialog.file to C++ QObject. Before I have used one object with methods and everything works well (QML calls method with QUrl argument which, in turn, calls QString case)

    Q_INVOKABLE void saveToFile(QUrl url) {saveToFile(url.toLocalFile())};
    Q_INVOKABLE void saveToFile(QString string){//some processing};
    

    Now I have base class with common method and virtual abstract one

    Q_INVOKABLE void saveToFile(QUrl url) {saveToFile(url.toLocalFile())};
    Q_INVOKABLE virtual void saveToFile(QString string) = 0;
    

    So in the derived class I have different definitions of the method void saveToFile(QString string). Following this idea, I try to call saveToFile from QML for the derived objects. But the override method is calling with converting (QML url to Qstring directly). How can I avoid this situation and call base method from QML? Of course I can give different names, but I'm interested in common case and, maybe, good practices.


  • Moderators

    In order to call the QUrl overload, you need to pass a url variable instead of string. Here is - somewhat hacky - solution:

    FileDialog {
    property url myUrl: file
    }
    // JS
    yourCppObject.saveToFile(myUrl)
    

    Not tested - I hope it will work though :P If not, then different method names is the right solution.



  • @sierdzio Hello and thank you for the fast reply! Looks like it failed to be workaround :) Moreover, it says in documentation that FileDialog.file is already url type. So looks like there is no difference for passing this argument.

    One more thing that I have tried and it works: redefine the method in the derived class with QUrl argument and call parent method directly:

    void Derived::saveToFile(QUrl filename) {
        Base::saveToFile(filename);
    }
    

    This workaround works and seems to be ok in my case.


  • Moderators

    Interesting! OK, nice that you've found a solution :-)



  • @St-Stanislav said in Call base object method from QML:

    void Derived::saveToFile(QUrl filename) {
    Parent::saveToFile(filename);
    }

    This is a C++ 'issue', you have to tell C++ compiler you want to keep previous definition:

    class BaseClass : public QObject
    {
        Q_OBJECT
    public:
        Q_INVOKABLE void saveToFile(QString string){//some processing};;
    }
    
    class DerivedClass : public BaseClass
    {
        Q_OBJECT
     
    public:
        using BaseClass::saveToFile;
        Q_INVOKABLE void saveToFile(QUrl url) {saveToFile(url.toLocalFile()); };
    }
    

    ==> http://www.cs.technion.ac.il/users/yechiel/c++-faq/hiding-rule.html



  • @KroMignon Yes, I have caught it and solved it in the same way, but I wondered if it's any chance to call base class method from QML directly :)



  • @St-Stanislav said in Call base object method from QML:

    if it's any chance to call base class method from QML directly :)

    What do you mean?

    myCppClass.saveToFile("TEST"); // => should call saveToFile(QString) 
    myCppClass.saveToFile(Qt.resolvedUrl("test.qml")); // => should call saveToFile(QUrl)
    


  • @KroMignon Well, looks like your solution is also not for me (cause of several methods with one name I have used the second solution from the link you posted). I get why this methods are called, get what solution I can use, but I was wondering if this problem can be solved from QML side :)
    I have created tiny example project, but have no idea how to post it here correctly.



  • I'm not sure if I understand things with total clarity.

    However, if I understand, then these both exist in a base class:

    /* (1) */ Q_INVOKABLE void saveToFile(QUrl url) {saveToFile(url.toLocalFile())};
    /* (2) */ Q_INVOKABLE virtual void saveToFile(QString string) = 0;
    

    And some QML code is triggering entry/execution into (2) instead of (1).

    In that case, I wonder why not just remove Q_INVOKABLE from (2) so that it is not-invokable from QML?


Log in to reply