1
votes

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?

1

1 Answers

0
votes

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
        }
    }
}