I am new and trying to learn qt and qml but I cannot find a way to solve this problem.
I have a QSqlTableModel with only 4 rows of test data, but I would like to convert distinct values from 1 column (of which there is only 1 value) into a list for a qml ListModel.
I have this Q_PROPERTY(QStringList distinctSemesters READ getSemesterList NOTIFY semesterChanged)
in my SqlDataModel.h file, with this in my sqldatamodel.cpp
QStringList SqlDataModel::getSemesterList() const
{
QStringList mySemesters;
QSqlQuery query;
query.exec("SELECT DISTINCT Semester FROM results");
while (query.next()) {
QString currentSemester = query.value(0).toString();
mySemesters << currentSemester;
}
return mySemesters;
}
Which returns a QStringList of length 1. I am trying to read this into my qml with
ListView {
model: SqlDataModel {
id: myModel
}
delegate: ItemDelegate {
width: parent.width
text: myModel.distinctSemesters
}
}
Which works in getting the String from the getSemesterList() function. But the String gets repeated in the listview 4 times (the size of my tablemodel). I have checked this and added more rows to the test table, which continues to repeat the same string more times in my listview.
From my limited understanding, I am guessing that this will always be the case because the listview is taking its size from the model - which is the size of the qsl table. I have no idea about how to go about this, can anyone else point me in the correct direction?
My current thoughts are to create a new sqlmodel to bring into the qml (but I need to read+write so I believe sqltablemodel is good for that), or should I try to fix qml side with javascript. I looked into it in javascript but when I tried
property ListModel distinctSemesters;
Component.onCompleted: {
console.log(distinctSemesters)
I kept getting errors that the distinctSemesters was undefined.
Any help is greatly appreciated thank you.
below (i hope) is a reproducible example. I have used some online resources to guide this. main.cpp:
int main(int argc, char *argv[])
{
initDatabase();
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
qmlRegisterType<SqlDataModel>("GradesSqlDataModel", 1, 0, "SqlDataModel");
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
SqlDataModel.h
class SqlDataModel : public QSqlTableModel
{
Q_OBJECT
Q_PROPERTY(QString semester READ getsemester WRITE setSemester NOTIFY semesterChanged)
Q_PROPERTY(QStringList distinctSemesters READ getSemesterList NOTIFY semesterChanged)
public:
SqlDataModel(QObject *parent = 0);
QStringList getSemesterList() const;
QString getsemester() const;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
signals:
void semesterChanged();
};
SqlDataModel.cpp
SqlDataModel::SqlDataModel(QObject *parent) :
QSqlTableModel(parent)
{
createTable();
setTable("Results");
setEditStrategy(QSqlTableModel::OnManualSubmit);
select();
}
QStringList SqlDataModel::getSemesterList() const
{
QStringList mySemesters;
QSqlQuery query;
query.exec("SELECT DISTINCT Semester FROM results");
while (query.next()) {
QString currentSemester = query.value(0).toString();
mySemesters << currentSemester;
qDebug() << currentSemester;
}
qDebug() << "length :" <<mySemesters.length();
return mySemesters;
}
QHash<int, QByteArray> SqlDataModel::roleNames() const
{
QHash<int, QByteArray> dataNames;
dataNames[Qt::UserRole] = "ID";
dataNames[Qt::UserRole + 1] = "Semester";
dataNames[Qt::UserRole + 2] = "CourseTitle";
dataNames[Qt::UserRole + 3] = "TestWeight";
dataNames[Qt::UserRole + 4] = "TestName";
dataNames[Qt::UserRole + 5] = "Result";
dataNames[Qt::UserRole + 6] = "OutOf";
qDebug() << "DataNames" << dataNames;
return dataNames;
}
QVariant SqlDataModel::data(const QModelIndex &index, int role) const
{
qDebug() << "settingData";
if (role < Qt::UserRole)
return QSqlTableModel::data(index, role);
const QSqlRecord sqlRecord = record(index.row());
return sqlRecord.value(role - Qt::UserRole);
}
main.qml
ApplicationWindow {
id: window;
visible: true;
width: 640;
height: 600;
title: qsTr("TEST")
Drawer {
id: drawer
width: Math.min(window.width, window.height) / 3 * 2
height: window.height
interactive: true
ListView {
model: SqlDataModel {
id: myModel
}
delegate: ItemDelegate {
width: parent.width
text: myModel.distinctSemesters
}
}
}
and my Results sql table looks like this (only with an ID primary key first):
query.exec("INSERT INTO results (Semester, CourseTitle, TestWeight, TestName, Result, OutOf) VALUES ('Spring 2020', 'Course 1', '10', 'Exam 1', 50, 100)");
query.exec("INSERT INTO results (Semester, CourseTitle, TestWeight, TestName, Result, OutOf) VALUES ('Spring 2020', 'Course 1', '33', 'Exam 2', 70, 100)");
query.exec("INSERT INTO results (Semester, CourseTitle, TestWeight, TestName, Result, OutOf) VALUES ('Spring 2020', 'Course 2', '25', 'Exam 1', 0, 100)");
query.exec("INSERT INTO results (Semester, CourseTitle, TestWeight, TestName, Result, OutOf) VALUES ('Spring 2020', 'Course 2', '5', 'Quiz 1', 5, 20)");