Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Unable to read data from QSqlTableModel in Qml : "role names" are not defined
QtWS25 Last Chance

Unable to read data from QSqlTableModel in Qml : "role names" are not defined

Scheduled Pinned Locked Moved Solved General and Desktop
sqlsqliteqsqltablemodelqmlc++ to qml
11 Posts 2 Posters 3.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    daljit97
    wrote on last edited by
    #1

    So I subclassed QSqlTableModel in my application. Then I set this model as a context property to be accessible in QML assigning it to a ListView. Then I set a simple Label as a delegate with text set to my role name (e.g. Name), but I always get the following error:

    ReferenceError: Name is not defined
    

    Below is my code

    #include "sqlmodel.h"
    #include <QSqlDatabase>
    #include <QSqlError>
    #include <QSqlRecord>
    #include <QStandardPaths>
    #include <QSqlQuery>
    
    SqlModel::SqlModel(QObject *parent )
        : QSqlTableModel( parent )
    {
        openDataBase();
    }
    QVariant SqlModel::data(const QModelIndex &index, int role) const{
    
        QVariant value;
        if(role < Qt::UserRole)
        {
            value = QSqlTableModel::data(index, role);
        }
        else {
            int columnIdx = role - Qt::UserRole - 1;
            QModelIndex modelIndex = this->index(index.row(), columnIdx);
            value = QSqlTableModel::data(modelIndex, Qt::DisplayRole);
        }
        return value;
    }
    
    QHash<int, QByteArray> SqlModel::roleNames() const
    {
    //    QHash<int, QByteArray> roles;
    //    roles[Qt::UserRole + 1] = "Identifier";
    //    roles[Qt::UserRole + 2] = "Name";
    //    roles[Qt::UserRole + 3] = "ElementColor";
    //    roles[Qt::UserRole + 4] = "FileUrl";
    //    roles[Qt::UserRole + 5] = "HomeRss";
    //    roles[Qt::UserRole + 6] = "ListPos";
    
    
    //    return roles;
        QHash<int, QByteArray> roles;
        for (int i = 0; i < this->columnCount(); i++) {
            QString role= this->headerData(i, Qt::Horizontal).toString();
            qDebug() << role;
            roles[Qt::UserRole + i + 1] = QVariant(role).toByteArray();
            qDebug()<<this->headerData(i, Qt::Horizontal);
        }
        return roles;
    }
    
    bool SqlModel::insertItem(const QVariantMap itemMap)
    {
        QSqlRecord sqlRecord = this->record();
        sqlRecord.setValue("Identifier", itemMap.value("Identifier").toInt());
        sqlRecord.setValue("Name", itemMap.value("Name").toString());
        sqlRecord.setValue("ElementColor", itemMap.value("ElementColor").toString());
        sqlRecord.setValue("FileUrl", itemMap.value("FileUrl").toString());
        sqlRecord.setValue("HomeRss", itemMap.value("HomeRss").toString());
        sqlRecord.setValue("ListPos",  itemMap.value("ListPos").toInt());
    
        bool success = this->insertRecord(rowCount(), sqlRecord);
    
        if(!success)
            qWarning() << "UNABLE TO ADD ITEM TO DATABASE" << this->lastError().text();
        else{
            this->submit();
        }
    }
    
    
    void SqlModel::openDataBase()
    {
        QSqlDatabase db;
    
        const QString DRIVER("QSQLITE");
    
        if(QSqlDatabase::isDriverAvailable(DRIVER)) {
            db = QSqlDatabase::addDatabase(DRIVER);
            QString storagePath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
            db.setDatabaseName(storagePath+"/database.sqlite");
    
            if(!db.open())
                qWarning() << "ERROR: " << db.lastError();
            else{
                qDebug( "Opening database %s", qPrintable( db.databaseName() ) );
                QSqlQuery query("CREATE TABLE IF NOT EXISTS home (Identifier INTEGER PRIMARY KEY,"
                                "Name TEXT, "
                                "ElementColor TEXT, "
                                "FileUrl TEXT, "
                                "HomeRss TEXT, "
                                "ListPos INTEGER)");
    
                if(!query.exec())
                    qWarning() << "DATABASE ERROR: " << query.lastError().text();
    
                this->setTable("home");
                this->setEditStrategy(QSqlTableModel::OnManualSubmit);
                this->select();
            }
        }
        else{
            qWarning() << "SQL DRIVER " << DRIVER << "NOT AVAILBLE" << db.lastError();
        }
    }
    
    
    1 Reply Last reply
    0
    • SGaistS SGaist

      That's because you are creating your database connection after you created your model. So the model is using the default database connection that hasn't been created yet.

      Move the database initialisation part outside of your model and somewhere before your create that object.

      D Offline
      D Offline
      daljit97
      wrote on last edited by
      #11

      @SGaist Ok that makes sense. Thank you

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #2

        Hi,

        Did you already saw that wiki entry about that subject ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        D 1 Reply Last reply
        0
        • SGaistS SGaist

          Hi,

          Did you already saw that wiki entry about that subject ?

          D Offline
          D Offline
          daljit97
          wrote on last edited by
          #3

          @SGaist said in Unable to read data from QSqlTableModel in Qml : "role names" are not defined:

          Hi,

          Did you already saw that wiki entry about that subject ?

          Yeah, my code is partially based on that

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #4

            Then can you also share the QtQuick part so your code can be properly tested ?

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            D 1 Reply Last reply
            0
            • SGaistS SGaist

              Then can you also share the QtQuick part so your code can be properly tested ?

              D Offline
              D Offline
              daljit97
              wrote on last edited by daljit97
              #5

              @SGaist yeah sure this is my qml:

              import QtQuick 2.9
              import QtQuick.Controls 2.2
              import QtQuick.Layouts 1.4
              
              ApplicationWindow {
                  visible: true
                  width: 640
                  height: 480
                  title: qsTr("Scroll")
              
                  ColumnLayout{
                      anchors.fill: parent
                      ScrollView {
                          Layout.fillWidth: true
                          Layout.fillHeight: true
                          ListView {
                              width: parent.width
                              model: sqlModel
              
                              delegate: ItemDelegate {
                                  text: "Item" + (Name) // if you remove (Name) and just put a string, then add it shows the string
                                  width: parent.width
                              }
                          }
                      }
              
                      Button{
                          z: 15
                          text: "Add"
                          onClicked:{
                              var milliseconds = new Date().getTime();
                              var myObject = {Identifier: milliseconds, Name: "MyItem", ElementColor: "blue", FileUrl: "http://", HomeRss: "http:??", ListPos: 0}
                              sqlModel.insertItem(myObject)
                          }
                      }
                  }
              }
              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #6

                I didn't realise, there missing parts like your model header and the main.cpp file.

                Is your project accessible somewhere ?

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                D 1 Reply Last reply
                0
                • SGaistS SGaist

                  I didn't realise, there missing parts like your model header and the main.cpp file.

                  Is your project accessible somewhere ?

                  D Offline
                  D Offline
                  daljit97
                  wrote on last edited by daljit97
                  #7

                  @SGaist said in Unable to read data from QSqlTableModel in Qml : "role names" are not defined:

                  I didn't realise, there missing parts like your model header and the main.cpp file.

                  Is your project accessible somewhere ?

                  Unfortunately not but the header and main file implementation is quite simple. Here is the header:

                  #include <QObject>
                  #include <QDebug>
                  #include <QSqlTableModel>
                  #include <QQmlAutoPropertyHelpers.h>
                  
                  class SqlModel : public QSqlTableModel
                  {
                      Q_OBJECT
                  public:
                      SqlModel(QObject* parent = nullptr);
                      Q_INVOKABLE QVariant data(const QModelIndex &index, int role) const override;
                      QHash<int, QByteArray> roleNames() const override;
                  
                      Q_INVOKABLE bool insertItem(const QVariantMap itemMap);
                  private:
                      void openDataBase();
                  };
                  

                  In my main.cpp I do the following:

                  #include "sqlmodel.h"
                  #include <QGuiApplication>
                  #include <QQmlApplicationEngine>
                  #include <QQmlContext>
                  
                  int main(int argc, char *argv[])
                  {
                      QGuiApplication app(argc, argv);
                      app.setOrganizationDomain("daljit97");
                  
                      qmlRegisterType<SqlModel>();
                  
                      SqlModel *sqlHomeModel = new SqlModel();
                      QQmlApplicationEngine engine;
                  
                      QQuickStyle::setStyle("Material");
                      QQmlContext *qmlContext = engine.rootContext();
                      qmlContext->setContextProperty("sqlHomeModel", sqlHomeModel);
                  
                      engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                  
                      if (engine.rootObjects().isEmpty())
                          return -1;
                  
                      return app.exec();
                  }
                  
                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #8

                    Sorry but with the current bits and pieces I don't have anything on screen. Can you maybe refactor that to ensure it goes up to the screen ?

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    D 1 Reply Last reply
                    0
                    • SGaistS SGaist

                      Sorry but with the current bits and pieces I don't have anything on screen. Can you maybe refactor that to ensure it goes up to the screen ?

                      D Offline
                      D Offline
                      daljit97
                      wrote on last edited by daljit97
                      #9

                      @SGaist Here I uploaded a fully working project where the problem persists https://www.dropbox.com/s/qsyqds61zxdxkyx/SqlModelTest.zip?dl=0.
                      When you click the add button, it shows: Name not defined.
                      EDIT: I also update the qml file example provided here

                      1 Reply Last reply
                      0
                      • SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #10

                        That's because you are creating your database connection after you created your model. So the model is using the default database connection that hasn't been created yet.

                        Move the database initialisation part outside of your model and somewhere before your create that object.

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        D 1 Reply Last reply
                        2
                        • SGaistS SGaist

                          That's because you are creating your database connection after you created your model. So the model is using the default database connection that hasn't been created yet.

                          Move the database initialisation part outside of your model and somewhere before your create that object.

                          D Offline
                          D Offline
                          daljit97
                          wrote on last edited by
                          #11

                          @SGaist Ok that makes sense. Thank you

                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved