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

Strange QSqlQueryModel and QML behavior



  • Hello all!
    I have the following issue: it's main cpp class backend that has

    public:
        Q_INVOKABLE WordsStorage* wordsStorage() {return &m_wordStorage;}
    private:
        static void registerQML() {qRegisterMetaType<WordsStorage*>("WordsStorage");
        }
        WordsStorage m_wordsStorage;
    

    WordStorage is following:

    class WordsStorage : public QSqlQueryModel
    {
        Q_OBJECT
        Q_PROPERTY(QString testString READ testString WRITE setTestString NOTIFY testStringChanged)
    
        Q_INVOKABLE QString testString() const;
    ...
    }
    

    It has all necessary methods to get database rows, but it looks like that QML doesn't call virtual QVariant data(const QModelIndex &index, int role) const override at all. So I have decided to check, if any of other methods are available and have added Q_PROPERY with testString. After calling appropriate function in QML I have the following:

    TypeError: Property 'testString' of object WordsStorage(0xdbb7b3f880) is not a function
    

    But this method is for Q_PROPERY and is even marked by my to test with Q_INVOKABLE.

    When WordsStorage was inherited from QAbstractListModel eveything was well (as well as displaying data), but it is no luck with QSqlQueryModel. What can be a root of my issue?



  • Well, after a some close investigation I have solved my issue. I could not call model's methods because of using the following syntax in delegate's items:

    model.close()
    

    So as far I understood in this case we don't have access directly to model's methods. But if I define my model as a context property:

    engine.rootContext()->setContextProperty("wordsStorage", backend.wordsStorage());
    

    everything works well and pretty enough.

    Finally QSqlQueryModel has nothing to do with it. Such thing happens with an arbitrary model.

    I'm going to mark this topic as 'solved', but anyway: is there a way to do this without using root context? Otherwise QML part is going to be full of this contexts in a large project. Is it okay or not?



  • Small update: I found that the query in my QSqlQueryModel was broken (has typo). After fixing the data method started to be called, but Q_INVOKABLE methods can not be called anyway. E.g. model.clear() causes
    TypeError: Property 'clear' of object QQmlDMAbstractItemModelData(someAddress) is not a function
    error. So I'm still in the dark.



  • Well, after a some close investigation I have solved my issue. I could not call model's methods because of using the following syntax in delegate's items:

    model.close()
    

    So as far I understood in this case we don't have access directly to model's methods. But if I define my model as a context property:

    engine.rootContext()->setContextProperty("wordsStorage", backend.wordsStorage());
    

    everything works well and pretty enough.

    Finally QSqlQueryModel has nothing to do with it. Such thing happens with an arbitrary model.

    I'm going to mark this topic as 'solved', but anyway: is there a way to do this without using root context? Otherwise QML part is going to be full of this contexts in a large project. Is it okay or not?


Log in to reply