Reputation: 157
I'm currently practicing the QML and I need to pass several data from the C++ to the Qml.
The aim of my "project" is to display data which were red from an external JSON file.
Example:
{
"entries":
[
{
"title": "test",
"description": "desc",
"command": "blabla"
},
{
"title": "test2",
"description": "desc2",
"command": "blabla2"
},
]
}
My first try was to parse and create a basic model like :
class Configuration : public QObject {
Q_OBJECT
public:
Q_INVOKABLE QString title(void) { return _title; }
Q_INVOKABLE QString description(void) { return _description; }
Q_INVOKABLE QString command(void) { return _command; }
void setTitle(const QString & title) { _title = title; }
void setDescription(const QString & desc) { _description = desc; }
void setCommand(const QString & command) { _command = command; }
...
private:
QString _title;
QString _description;
QString _command;
...
and to pass this model with _engine->rootContext()->setContextProperty("itemsModel", _configuration);
(_engine
is of type : QQmlApplicationEngine)
But with this solution, I'm not able to call these methods because this class has a "custom" type (not recognized from the Qml).
So I'm searching a way to create and to properly share my data from the C++ to the QML :)
Upvotes: 1
Views: 1463
Reputation: 244282
The logic is to convert the json into a Qt model (a class that inherits from QAbstractItemModel) and that can be done from:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QVariant>
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
const QString data = R"({
"entries": [{
"title": "test",
"description": "desc",
"command": "blabla"
},
{
"title": "test2",
"description": "desc2",
"command": "blabla2"
}
]
})";
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("jsonData", data);
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();
}
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
ListView{
id: view
model: listModel
anchors.fill: parent
delegate:Text{
width: parent.width
text: model.title + " " + model.description + " " + model.command
}
}
ListModel{
id: listModel
dynamicRoles: true
}
Component.onCompleted: {
var o = JSON.parse(jsonData);
var entries = o["entries"];
for(var i in entries){
var entry = entries[i]
listModel.append(entry)
}
}
}
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QStandardItemModel>
#include <QVariant>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
class EntryModel: public QStandardItemModel{
public:
enum EntryRole{
TitleRole = Qt::UserRole,
DescriptionRole,
CommandRole
};
EntryModel(QObject *parent=nullptr): QStandardItemModel(parent){
QHash<int, QByteArray> roles;
roles[TitleRole]= "title";
roles[DescriptionRole]= "description";
roles[CommandRole]= "command";
setItemRoleNames(roles);
}
void append(const QString & title, const QString & description, const QString &command){
QStandardItem *item = new QStandardItem;
item->setData(title, TitleRole);
item->setData(description, DescriptionRole);
item->setData(command, CommandRole);
appendRow(item);
}
};
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
const QByteArray data = R"({
"entries": [{
"title": "test",
"description": "desc",
"command": "blabla"
},
{
"title": "test2",
"description": "desc2",
"command": "blabla2"
}
]
})";
QGuiApplication app(argc, argv);
EntryModel model;
QJsonDocument doc = QJsonDocument::fromJson(data);
QJsonArray entries = doc["entries"].toArray();
for(const QJsonValueRef & r: entries){
QJsonObject entry = r.toObject();
model.append(entry["title"].toString(), entry["description"].toString(), entry["command"].toString());
}
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("entryModel", &model);
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();
}
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
ListView{
id: view
model: entryModel
anchors.fill: parent
delegate:Text{
width: parent.width
text: model.title + " " + model.description + " " + model.command
}
}
}
Upvotes: 1