[Solved] best way to delegate through sqlite data for qml list view



  • Hey,

    I am searching for a simple way to get data from sqlite and put it in my list view.
    solutions i found so far is to include a model from c++ or use javascript to get the data.
    when i use the javascript method i am not sure how i should create a model out of the data i get from sql to pass it to the listview.

    can anyone help me?

    is there maybe a better way to delegate through my data?
    all examples i saw so far only take one value from the database or make a string out of several databse items and then put it in as an text property. i have seen no example where many db entrys get inserted into qml.


  • Lifetime Qt Champion



  • Hi SGaist,

    thanks for the link. I thought that there is maybe an easier way to do this only with qml but to do it with c++ gives much more possibilities.

    I tried the example in the link but got an error.
    I am having the problem that RoleNameHash seems not to be defined/included.
    @
    'RoleNameHash' does not name a type@

    @#ifndef SQLQUERYMODEL_H
    #define SQLQUERYMODEL_H

    #include <QtSql>

    class SqlQueryModel: public QSqlQueryModel
    {
    Q_OBJECT
    QHash<int,QByteArray> *hash;
    public:
    explicit SqlQueryModel(QObject * parent) : QSqlQueryModel(parent)
    {
    hash = new QHash<int,QByteArray>;
    hash->insert(Qt::UserRole, QByteArray("someRoleName"));
    hash->insert(Qt::UserRole + 1, QByteArray("otherRoleName"));
    }
    QVariant data(const QModelIndex &index, int role) const
    {
    if(role < Qt::UserRole) {
    return QSqlQueryModel::data(index, role);
    }
    QSqlRecord r = record(index.row());
    return r.value(QString(hash->value(role))).toString();
    }
    inline RoleNameHash roleNames() const { return *hash; }
    };

    #endif // SQLQUERYMODEL_H @



  • Ich changed the line to:
    @inline QHash<int,QByteArray> roleNames() const { return *hash; }@

    now i get:
    @QSqlQuery::exec: database not open@

    I think I should read me deeper into the whole QT SQL topic.



  • Hey,

    i solved it. It is really simple. I am wondering why there is not such an simple example anywhere.

    main.cpp
    @
    #include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlComponent>
    #include <QQmlContext>
    #include <QtSql/QSqlDatabase>
    #include <QtSql/QSqlQueryModel>
    #include <QtSql/QSqlQuery>
    #include <QDebug>

    int main(int argc, char *argv[])
    {
    QApplication app(argc, argv);

    QQmlApplicationEngine engine;
    
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("my.db.sqlite");
    if(!db.open()){
        qDebug("not open!");
    }else{
        qDebug("db open!");
    
    }
    
    //QSqlQuery drop("drop table List;");
    //QSqlQuery create("create table List (sample_text char(200));");
    QSqlQuery insert("insert into List values (\"some blaaahahhh!\");");
    
    //drop.exec&#40;&#41;;
    //create.exec&#40;&#41;;
    insert.exec&#40;&#41;;
    
    
    QSqlQueryModel *someSqlModel = new QSqlQueryModel();
    someSqlModel->setQuery("SELECT * FROM List");
    
    //db.close();
    engine.rootContext()->setContextProperty("datamodel", someSqlModel);
    
    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
    
    return app.exec();
    

    }@

    in the qml:

    @ Rectangle {
    ListView {
    width: 200; height: 200
    model: datamodel
    delegate: Row {
    Rectangle {
    width: 100; height: 40
    Text {
    anchors.fill: parent
    text: display
    }
    }
    }
    }
    }@



  • Ah, one thing i dont understand is how i can get different rows of the result in my qml delegate. at the moment there is:
    @
    text: display@

    this has nothing to do with my data. is this something like a wildcard?
    in my opninion it should look like the following but this is not working:

    @
    text: sample_text @


  • Lifetime Qt Champion

    If you want to display different things, you have to provide you own roles and use them to access your model



  • I realized it just some seconds ago. thanks anyways.

    here is my current implementation:

    @#ifndef SQLQUERYMODEL_H
    #define SQLQUERYMODEL_H

    #include <QtSql>
    #include <QAbstractItemModel>

    class SqlQueryModel: public QSqlQueryModel
    {
    Q_OBJECT
    QHash<int,QByteArray> *hash;
    public:
    explicit SqlQueryModel() : QSqlQueryModel()
    {
    hash = new QHash<int,QByteArray>;
    hash->insert(Qt::UserRole, QByteArray("name"));
    hash->insert(Qt::UserRole + 1, QByteArray("title"));
    }
    QVariant data(const QModelIndex &index, int role) const
    {
    if(role < Qt::UserRole) {
    return QSqlQueryModel::data(index, role);
    }
    QSqlRecord r = record(index.row());
    return r.value(QString(hash->value(role))).toString();
    }
    inline QHash<int, QByteArray> roleNames() const { return *hash; }
    };

    #endif // SQLQUERYMODEL_H
    @


  • Lifetime Qt Champion

    One thing you should change: don't use pointers to QHash, there's no need for that. Qt uses implicit sharing for it's containers class as well as heap allocation so you would only rarely need to allocate a QHash on the heap. Also, you don't delete it in any destructor so you are creating a memory leak.



  • Thanks for the hint. I changed this already. Should I add a destructor or do you think it is enough when i store it only on the stack instead of the heap...


  • Lifetime Qt Champion

    It's up to you, you can also use a QScopedPointer so you don't have to delete someSqlModel yourself


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.