I can't use QSqlQueryModel qt 5.3



  • I've a sqlite db and I want to display a query result on a qtquick listview.

    I've write this class, overwriting QSqlQueryMode:

    @#include <QSqlQueryModel>
    #include <QtQuick/QQuickItem>
    #include <QSqlError>
    #include <QtDebug>
    class ListSongModel : public QSqlQueryModel
    {
    Q_OBJECT

    private:
    QStringList _columnNames;
    public:

    const char* COLUMN_NAMES[5] = {
    "Filename",
    "Title",
    "Artist",
    "Length",
    NULL
    };

    const QString SQL_SELECT=QObject::tr("SELECT Filename, Title, Artist, Length FROM Media ORDER BY Title");

    void refresh()
    {
    setQuery(SQL_SELECT);
    if(lastError().type()>0)
    qDebug()<<"set query error: "+lastError().text();

      int i=0;
      while(COLUMN_NAMES[i])
      {
          setHeaderData(i,Qt::Horizontal, QObject::tr(COLUMN_NAMES[i]));
          i++;
      }
    

    }
    explicit ListSongModel(QObject *parent = 0) :
    QSqlQueryModel(parent)
    {
    refresh();
    }

    virtual QHash<int, QByteArray> roleNames() const
    {
    QHash<int, QByteArray> roleNames;
    int idx = 0;
    while( COLUMN_NAMES[idx]) {
    roleNames[Qt::UserRole + idx + 1] = COLUMN_NAMES[idx];
    idx++;
    }

       return roleNames;
    

    }

    QVariant data(const QModelIndex &index, int role) const
    {
        QVariant value = QSqlQueryModel::data(index, role);
        if(role < Qt::UserRole)
        {
            value = QSqlQueryModel::data(index, role);
        }
        else
        {
            int columnIdx = role - Qt::UserRole - 1;
            QModelIndex modelIndex = this->index(index.row(), columnIdx);
            value = QSqlQueryModel::data(modelIndex, Qt::DisplayRole);
        }
        return value;
    }
    

    };
    @

    And then I set the property in the qml context
    @ListSongModel songModel;
    rootContext()->setContextProperty("ModelSong", &songModel);@

    The problem is that the qml listview display correctly only the first page, if I scroll down I see only a black list, and then when I scroll up in the list remains only the first element.
    What can I do?

    Thanks
    Regards Andrea



  • Hi, just guessing but maybe you're running out of roles.
    In your roleNames function, the roleNames QHash instance you return are deleted at function exit, so when you scroll perhaps the heap loses sight of that QHash instance and gives you black contents. Try changing that QHash variable to a class member...



  • I think that this is not the problem, because I've tried this:

    @ virtual QHash<int, QByteArray> roleNames() const
    {
    QHash<int, QByteArray> *roleNames= new QHash<int, QByteArray>();

       for (int i=0;i<COLUMN_NAMES.count();i++)
       {
           (*roleNames)[Qt::UserRole + i +1] = COLUMN_NAMES.at(i).toLatin1();
       }
    
       return *roleNames;
    

    }@

    And I've the same issue
    Regards Andrea


  • Lifetime Qt Champion

    Hi,

    Why are you allocating that hash on the heap ?
    From Qt's documenation:
    @
    QHash<int, QByteArray> AnimalModel::roleNames() const {
    QHash<int, QByteArray> roles;
    roles[TypeRole] = "type";
    roles[SizeRole] = "size";
    return roles;
    }@



  • Hi,
    Because hskoglund wrote that " QHash instance you return are deleted at function exit" so I've tried to allocate it on the heap. (but it was only a test)

    I can't declare "QHash" as class attribute because roleNames is virtual.

    So or I did not understand what you said to do or I do not know what should I do.

    EDIT:
    now I've understand!
    I had instanced my entire object on the heap, and now works

    @ ListSongModel *songModel = new ListSongModel(this);
    rootContext()->setContextProperty("ModelSong", songModel);@

    Thank you very much!


  • Lifetime Qt Champion

    Where did I write that ?

    You don't need to, just update the code from the example with your values.
    Based on your last example:
    @
    virtual QHash<int, QByteArray> roleNames() const
    {
    QHash<int, QByteArray> roles;

       for (int i=0;i<COLUMN_NAMES.count();i++) {
           roles[Qt::UserRole + i +1] = COLUMN_NAMES.at(i).toLatin1();
       }
    
       return roles;
    

    }@


Log in to reply
 

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