Hi there,
the last days i searched for a solution to display a QSqlQueryModel in a QML TableView. I found these really helpful links:
QML and QSqlTableModel [qt-project.org]
How to use a QSqlQueryModel [qt-project.org]
Using QtSql database access [forum.dailymobile.net]
So i derived my own class from QSqlQueryModel and reimplemented roleNames() [doc.qt.io] because setRoleNames() [doc.qt.io] is obsolete in Qt 5.4.
HEADER
class SQLiteModel : public QSqlQueryModel {
Q_OBJECT
public:
explicit SQLiteModel(QObject *parent = NULL);
~SQLiteModel();
Q_INVOKABLE bool setDatabase(const QString &database);
Q_INVOKABLE bool setQuery(const QString &query);
virtual QHash<int, QByteArray> roleNames() const;
static void declareQML();
private:
QSqlDatabase _db;
static QString _connection();
};
SOURCE
SQLiteModel::SQLiteModel(QObject *parent) :
QSqlQueryModel(parent) {
_db = QSqlDatabase::addDatabase("QSQLITE", SQLiteModel::_connection());
}
SQLiteModel::~SQLiteModel() {
if (_db.open()) _db.close();
}
bool SQLiteModel::setDatabase(const QString &database) {
if (!QFileInfo(database).exists()) {
qWarning() << "SQLiteModel::setDatabase() - Could not find database '" + database + "'";
return false;
}
if (_db.open()) {
_db.close();
this->clear();
}
_db.setDatabaseName(database);
if (!_db.open()) {
qWarning() << "SQLiteModel::setDatabase() -" << database;
return false;
}
return true;
}
bool SQLiteModel::setQuery(const QString &query) {
QSqlQueryModel::setQuery(query, _db);
if (this->query().record().isEmpty()) {
qWarning() << "SQLiteModel::setQuery() -" << this->query().lastError();
return false;
}
return true;
}
QHash<int, QByteArray> SQLiteModel::roleNames() const {
QHash<int, QByteArray> roles;
qWarning() << "SQLiteModel::roleNames()";
for (int i = 0; i < this->record().count(); i++) {
roles[Qt::UserRole + i + 1] = this->record().fieldName(i).toLocal8Bit();
}
return roles;
}
void SQLiteModel::declareQML() {
qmlRegisterType<SQLiteModel>("Extensions", 1, 0, "SQLiteModel");
}
QString SQLiteModel::_connection() {
static int ID = 0; ID++;
return "SQLiteModelConnection" + QString::number(ID);
}
But the QML TableView does not show anything. I know the class is working, because a QTableView could display the model. (Example for a SQLite database with ‘Components’ table and ‘ID’, ‘Name’, ‘Description’ and ‘Value’ header)
MAIN
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
SQLiteModel::declareQML();
SQLiteModel *model = new SQLiteModel;
model->setDatabase("../../database");
model->setQuery("select * from Components");
QTableView *view = new QTableView;
view->setModel(model);
view->show();
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("SQLite", model);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
QML
ApplicationWindow {
title: qsTr("SQL Demo")
width: 640
height: 480
visible: true
minimumWidth: 640
minimumHeight: 480
TableView {
id: tableview
anchors.fill: parent
anchors.margins: 10
TableViewColumn { role: "ID" ; title: "ID"; visible: true }
TableViewColumn { role: "Name" ; title: "Name" }
TableViewColumn { role: "Description" ; title: "Description" }
TableViewColumn { role: "Value" ; title: "Value" }
model: SQLite
}
}
Any suggestions? I also tried to add a Q_INVOKABLE before the roleNames() function, but it didn’t changed anything.
Regards,
MrFog
↧









