Reputation: 13
In my TableView
I have ListModel
that is filled by user. I wanna save this model as a .csv file using python. But I can't send model via qml signal to pyqt (there is no type for models), and if I want to access this ListModel
in python using this line.
Python
model = self.engine.rootObjects()[0].findChild(QObject, "newCsvModel")
In return I get QAbstractListModel
, which (in my understanding) doesn't hold model content.
QML
This is how I use my model
TableView {
model: ListModel{
id: csvModel
objectName: "newCsvModel"
ListElement{
key1: "val1"
key2: "val2"
...
}
...
}
I have a class for sending the exact type of model from pyqt to qml and it works fine, but doing it the other way around is problematic for me. Do you know how extract data from qml ListModel?
Upvotes: 1
Views: 783
Reputation: 243975
You should not export directly to a QML object, instead use a QObject that fetches the QML object through a slot obtaining the model, accessing the roles and values to save it in a .csv.
import csv
from PyQt5 import QtCore, QtGui, QtQml
class CSVHelper(QtCore.QObject):
@QtCore.pyqtSlot("QAbstractItemModel*", str)
def saveListModel(self, model, filename):
headers = {v.data().decode(): k for k, v in model.roleNames().items()}
with open(filename, mode="w") as csv_file:
writer = csv.DictWriter(csv_file, fieldnames=headers.keys())
writer.writeheader()
for i in range(model.rowCount()):
row = dict()
for name, role in headers.items():
value = model.index(i, 0).data(role)
row[name] = value
writer.writerow(row)
if __name__ == "__main__":
import os
import sys
app = QtGui.QGuiApplication(sys.argv)
csv_helper = CSVHelper()
engine = QtQml.QQmlApplicationEngine()
engine.rootContext().setContextProperty("CSVHelper", csv_helper)
file = os.path.join(os.path.dirname(os.path.realpath(__file__)), "main.qml")
engine.load(QtCore.QUrl.fromLocalFile(file))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec())
main.qml
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Controls 1.4
ApplicationWindow {
id: root
visible: true
width: 640
height: 480
ListModel {
id: libraryModel
ListElement {
title: "A Masterpiece"
author: "Gabriel"
}
ListElement {
title: "Brilliance"
author: "Jens"
}
ListElement {
title: "Outstanding"
author: "Frederik"
}
}
Column{
Button {
text: "Press me"
onClicked: CSVHelper.saveListModel(libraryModel, "data.csv")
}
TableView {
width: root.width
height: 400
TableViewColumn {
role: "title"
title: "Title"
width: 100
}
TableViewColumn {
role: "author"
title: "Author"
width: 200
}
model: libraryModel
}
}
}
Upvotes: 1