simon
simon

Reputation: 1234

Access QList object in QML

I have a little problem accessing a QList objects since Javascript. I have a C ++ class that allows me to perform SQL queries since QML / JS. Everything works, I get my results in C ++.

My problem is that I'd returned to QML an QList object. This is my function in C++ to return SQL result (Note is a simple object with different attributes) :

QList<Note> Storage::setQuery(QString query)
{
    QList<Note> noteItems;
    QSqlQuery qsqlQuery;
    bool ok = qsqlQuery.exec(query);
    if(!ok)
    {
        qDebug() << "Error setQuery" << m_sqlDatabase.lastError();
    }
    else
    {

        while (qsqlQuery.next()) {
            Note my_note;
            QString note = qsqlQuery.value("message").toString();
            my_note.setMessage(note);

            noteItems.append(my_note);
        }
   }

   return noteItems;
}

But when I call this function from JS I get this error: Unknown method return type: QList<Note> The problem is the return type, QML JS doesn't know the type QList<Object>, why? What do I do wrong

Upvotes: 1

Views: 2474

Answers (2)

Vedanshu
Vedanshu

Reputation: 2296

If you want to use c++ QList as a model in Qml, I would recommend you to use the following procedure. I'm using my own example, you might change it according to your needs.

Storage.h

class Storage : public QObject {
    Q_PROPERTY(QQmlListProperty<Note> getList READ getList)

public:
    QQmlListProperty<Note> getList();
    void setQuery(QString query);
    QList<Note> noteItems;;
private:
    static void appendList(QQmlListProperty<Note> *property, Note *note);
    static Note* cardAt(QQmlListProperty<Note> *property, int index);
    static int listSize(QQmlListProperty<Note> *property);
    static void clearListPtr(QQmlListProperty<Note> *property);
};

Storage.cpp

void Field::appendList(QQmlListProperty<Card> *property, Note *note) {
    Q_UNUSED(property);
    Q_UNUSED(note);
}

Note* Field::cardAt(QQmlListProperty<Note> *property, int index) {
    return static_cast< QList<Note> *>(property->data)->at(index);
}

int Field::listSize(QQmlListProperty<Note> *property) {
    return static_cast< QList<Note> *>(property->data)->size();
}
void Field::clearListPtr(QQmlListProperty<Note> *property) {
    return static_cast< QList<Note> *>(property->data)->clear();
}

QQmlListProperty<Note> Field::getList() {
    return QQmlListProperty<Note>( this, &list[0], &appendList, &listSize, &cardAt,  &clearListPtr );
}

void Storage::setQuery(QString query)
{
    QList<Note> noteItems;
    QSqlQuery qsqlQuery;
    bool ok = qsqlQuery.exec(query);
    if(!ok)
    {
        qDebug() << "Error setQuery" << m_sqlDatabase.lastError();
    }
    else
    {

        while (qsqlQuery.next()) {
            Note my_note;
            QString note = qsqlQuery.value("message").toString();
            my_note.setMessage(note);

            noteItems.append(my_note);
        }
   }
}

main.cpp

int main(int argc, char *argv[])
{
    qmlRegisterType<Note>();
}

The QQmlListProperty class allows applications to expose list-like properties to QML. To provide a list property, a C++ class must implement the operation callbacks, and then return an appropriate QQmlListProperty value from the property getter. List properties should have no setter. When extending QML with C++ code, a C++ class can be registered with the QML type system to enable the class to be used as a data type within QML code.

Upvotes: 2

milianw
milianw

Reputation: 5336

Did you register Note as a meta type? Probably that's what's missing:

http://doc.qt.io/qt-5/qmetatype.html#Q_DECLARE_METATYPE

In Qt 4 you'll also have to register QList<Note>, but not in Qt 5.

Oh, and Note should probably be a Q_GADGET, otherwise you cannot access its contents from QML either. Make sure you use Qt 5.5+. Otherwise, you'll need QList<Note*> and make those Note objects inherit from QObject.

Upvotes: 1

Related Questions