Naveen
Naveen

Reputation: 852

How to add data to a model dynamically in qml?

i am building a music player app where i need to load the song data based on the album name. I have initialised my model by passing the model object to qml like this in main.cpp file

      albumSongs globalSongListModel;
      ctxt->setContextProperty("globalSongListModel", &globalSongListModel);

in this class albumSongs i have the following properties

Q_PROPERTY(QString songName READ songName CONSTANT)
Q_PROPERTY(QString songFileUrl READ songFileUrl CONSTANT)
Q_PROPERTY(QString songDuration READ songDuration CONSTANT)

I have a public slot in the albumSongs class which gets the data from the qml event

public slots:
    QList<QObject*> getSongListByAlbumName(QString albumName){
        dbHelper dbh;
        QList<QObject*> songList;
        dbh.loadDataByAlbumName(albumName, songList);
        return songList;

    }

the loadDataByAlbumName() function is declared in dbhelper class as follows

void dbHelper::loadDataByAlbumName(QString albumName, QList<QObject*>& songList) {
    QString query = "SELECT " + this->LI_DATA_TABLE_COLUMN_ONE + "," + this->LI_DATA_TABLE_COLUMN_TWO + "," + this->LI_DATA_TABLE_COLUMN_NINE +  " FROM " + this->LI_DATA_TABLE_NAME + " WHERE " + this->LI_DATA_TABLE_COLUMN_THREE + "=?";
    QSqlQuery sql;
    sql.prepare(query);
    sql.bindValue(0, albumName);
    sql.exec();
    while (sql.next()) {
        QString songName = sql.value(0).toString();
        QString songUrl = sql.value(1).toString();
        QString songDuration = sql.value(2).toString();
        songList.append(new albumSongs(songName, songUrl, songDuration));
    }
}

i can successfully load the data from db to the QListsongList But when i try to use it in the qml file like this

ListView {
    id: song_list_view
    width: 180; height: 200
    anchors.top: name.bottom;
    anchors.topMargin: 30
    delegate: Text {
        text: songName + " " + songFileUrl
    }




}

i get the error in delegate column stating that songName is not defined.

I have been setting this model on mouse enter event like this

  onEntered: {
            song_list_view.model = globalSongListModel.getSongListByAlbumName(globalName)

        }

Is this correct way of doing this task? What should i do to resolve the error?

Upvotes: 2

Views: 1090

Answers (1)

eyllanesc
eyllanesc

Reputation: 243945

First of all you have a bad design: how an albumSongs has a songName, songFileUrl and songDuration ?, in fact you must have a class that stores the data of a Song and another class manager that has the slot that returns the list.

Going to the problem, when the model is a list then you must use modelData to access each item, but you still can not access the properties because QML does not know that class so you must register it with qmlRegisterUncreatableType() so that you can access the properties but not create objects of that class in QML:

class Song : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString songName READ songName CONSTANT)
    Q_PROPERTY(QString songFileUrl READ songFileUrl CONSTANT)
    Q_PROPERTY(QString songDuration READ songDuration CONSTANT)
public:
    explicit Song(const QString & songName="",
                  const QString & songFileUrl="",
                  const QString & songDuration="",
                  QObject *parent = nullptr):
        QObject(parent),
        m_songName(songName),
        m_songFileUrl(songFileUrl),
        m_songDuration(songDuration)
    {}
    QString songName() const{
        return m_songName;
    }

    QString songFileUrl() const{
        return  m_songFileUrl;
    }
    QString songDuration() const{
        return m_songDuration;
    }

private:
    QString m_songName;
    QString m_songFileUrl;
    QString m_songDuration;
};

class SongManager: public QObject{
    Q_OBJECT
public:
    explicit SongManager(QObject *parent=nullptr):
        QObject(parent)
    {}
public slots:
    static QList<QObject*> getSongListByAlbumName(const QString & name){
        QList<QObject*> songList;
        dbHelper dbh;
        dbh.loadDataByAlbumName(albumName, songList);
        return songList;
    }
};

main.cpp

// ...
qmlRegisterUncreatableType<Song>("Songs", 1, 0, "Song", "Error class uncreatable");
// ...
SongManager manager;
ctxt->setContextProperty("manager", &manager);
// ...

*.qml

// ...
import Songs 1.0
// ...
ListView {
    id: song_list_view
    width: 180; height: 200
    anchors.top: name.bottom;
    anchors.topMargin: 30
    delegate: Text {
        text: modelData.songName + " " + modelData.songFileUrl
    }
}
// ...
onEntered: song_list_view.model = manager.getSongListByAlbumName(globalName)

Upvotes: 1

Related Questions