sqliteqtqmlqlistviewqsqlquerymodel

I get undefined data from QSqlQueryModel in my ListView QML (SQLite database)


I am trying to display data that is in two tables in the same database. The tables in the database plan_db.sqlite were created using these queries:

CREATE TABLE PlanOne (ID INTEGER NOT NULL PRIMARY KEY, Time VARCHAR(5), Name VARCHAR(50));

CREATE TABLE PlanTwo (ID INTEGER NOT NULL PRIMARY KEY, Time VARCHAR(5), Name VARCHAR(50));

After inserting some data the structure of it looks like this:

PlanOne:
1|10:00|Event 1
2|14:00|Event 2
PlanTwo:
1|12:00|Event 3
2|16:00|Event 4

The connection is estabilished in the class DatabaseHandler:

QSqlDatabase plan_db = QSqlDatabase::addDatabase("QSQLITE", "plan_connection");

Then I have two QSqlQueryModels that are supposed to represent the data from two tables: PlanOne and PlanTwo:

MySqlModelOne:

class MySqlModelOne : public QSqlQueryModel
{
    Q_OBJECT

public:
    explicit MySqlModelOne(QObject* parent = Q_NULLPTR);
    Q_INVOKABLE void refresh();
    QHash<int, QByteArray> roleNames() const override;
    QVariant data(const QModelIndex &index, int role) const override;

private:
    QSqlDatabase plan_db = QSqlDatabase::database("plan_connection");
    QSqlQuery plan_qry;

    const static char* COLUMN_NAMES[];
    const static char* SQL_SELECT;
};


MySqlModelOne::MySqlModelOne(QObject* parent) : QSqlQueryModel(parent)
{
    if (plan_db.open()) qDebug("Plan database opened");
    else qDebug("Plan database not opened");

    plan_qry = QSqlQuery(plan_db);

    refresh();
}

void MySqlModelOne::refresh()
{
    plan_qry.exec(SQL_SELECT);
    this->setQuery(plan_qry);
}

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

QVariant MySqlModelOne::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;
}

const char* MySqlModelOne::COLUMN_NAMES[] = { "ID", "Time", "Name", NULL};

const char* MySqlModelOne::SQL_SELECT = "SELECT * FROM PlanOne";

MySqlModelTwo is the copy of MySqlModelOne with appropriate changes like swapping every One with Two e.g:

const char* MySqlModelTwo::SQL_SELECT = "SELECT * FROM PlanTwo";

The classes are properly exposed to QML in main.cpp:

qmlRegisterType<MySqlModelOne>("com.sweak.mysqlmodelone", 1, 0, "MySqlModelOne");
qmlRegisterType<MySqlModelTwo>("com.sweak.mysqlmodeltwo", 1, 0, "MySqlModelTwo");
qmlRegisterType<DatabaseHandler>("com.sweak.databasehandler", 1, 0, "DatabaseHandler");

And finally the QML code that is supposed to display the data from QSqlQueryModels using ListViews:

Window {
    width: 640
    height: 480
    visible: true

    DatabaseHandler {
        id: dataBaseHandler
    }

    MySqlModelOne {
        id: modelOne
    }

    MySqlModelTwo {
        id: modelTwo
    }

    ListView {
        id: listViewOne
        model: modelOne
        width: 100
        height: width
        anchors.left: parent.left
        delegate: RowLayout {
            Text {
                text: modelOne.Time
            }
            Text {
                text: modelOne.Name
            }
        }
    }

    ListView {
        id: listViewTwo
        model: modelTwo
        width: 100
        height: width
        anchors.left: listViewOne.right
        delegate: RowLayout {
            Text {
                text: modelTwo.Time
            }
            Text {
                text: modelTwo.Name
            }
        }
    }

After executing the program, the program window is blank (obviously) and I get the following error messages:

Plan database opened
Plan database opened
qrc:/main.qml:42:17: Unable to assign [undefined] to QString
qrc:/main.qml:45:17: Unable to assign [undefined] to QString
qrc:/main.qml:42:17: Unable to assign [undefined] to QString
qrc:/main.qml:45:17: Unable to assign [undefined] to QString
qrc:/main.qml:66:17: Unable to assign [undefined] to QString
qrc:/main.qml:69:17: Unable to assign [undefined] to QString
qrc:/main.qml:66:17: Unable to assign [undefined] to QString
qrc:/main.qml:69:17: Unable to assign [undefined] to QString

First two lines assure me that the database was properly opened in both QSqlQueryModels but 8 lines that come next suggest to me that the data might not have been retrieved from both tables or it was retrieved but the format is undefined and obviously can't be assigned to QString and consequently can't be displayed via the ListViews. Can the problem be in the fact that I try to retrieve the data simultaneously from the same database through two different models? If so, how can I do this without causing such errors? Or maybe You have other ideas how to retrieve data from different tables in the same database using QSqlQueryModel.


Solution

  • The problem was in the QML part of the program. After binding the ModelOne and ModelTwo to the property model of each of the ListViews while trying to get access to the fields in tables there was no need to to do this this way:

    Text {
        text: modelOne.Time
    }
    

    instead it should have been:

    Text {
        text: Time
    }