4

Hello I am using Model class to supply items for lists and comboboxes. The problem is that I use the setContextProperty() function every time for each element. I'm looking for a solution where all elements(list and comboboxes) use the same ContextProperty. Furthermore with this way I guess JSON files can be loaded dynamically instead of loading all of them at the beginning.

main.py

class Model(QAbstractListModel, QObject):
    """ it reads JSON file, that is given as argument,
    and creates the model"""

if __name__ == "__main__":
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()

    model1 = Model("file1.json")
    model2 = Model("file2.json")
    model3 = Model("file3.json")
    model4 = Model("file4.json")
    model5 = Model("file5.json")

    engine.rootContext().setContextProperty("model1", model1)
    engine.rootContext().setContextProperty("model2", model2)
    engine.rootContext().setContextProperty("model3", model3)
    engine.rootContext().setContextProperty("model4", model4)
    engine.rootContext().setContextProperty("model5", model5)

    engine.rootContext().setContextProperty("applicationDirPath", os.path.dirname(__file__))
    engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))

    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec())
Reactionic
  • 182
  • 1
  • 2
  • 12
  • @Adib I wanted to keep whole backend stuff on python side. With the same *Model class* I can also add and delete an item in JSON file. – Reactionic Aug 01 '21 at 19:04

1 Answers1

5

You can create a QObject that exposes all the models as a property list and then use a Repeater to dynamically create the comboboxes.

The following is a demo:

import os
import sys
from pathlib import Path

from PySide6.QtCore import Property, QCoreApplication, QObject, Qt, QUrl, Signal
from PySide6.QtGui import QGuiApplication, QStandardItem, QStandardItemModel
from PySide6.QtQml import QQmlApplicationEngine

CURRENT_DIRECTORY = Path(__file__).resolve().parent


class Model(QStandardItemModel):
    def __init__(self, values, parent=None):
        super().__init__(parent)
        for value in values:
            item = QStandardItem(value)
            self.appendRow(item)


class Manager(QObject):
    models_changed = Signal(name="modelsChanged")

    def __init__(self, parent=None):
        super().__init__(parent)
        self._models = []

    @Property("QVariantList", notify=models_changed)
    def models(self):
        return self._models

    def append_model(self, model):
        self._models.append(model)
        self.models_changed.emit()


def main():
    app = QGuiApplication(sys.argv)

    manager = Manager(app)

    manager.append_model(Model(["item11", "item12", "item13"]))
    manager.append_model(Model(["item21", "item22", "item23"]))
    manager.append_model(Model(["item31", "item32", "item33"]))
    manager.append_model(Model(["item41", "item42", "item43"]))

    engine = QQmlApplicationEngine()

    context = engine.rootContext()
    context.setContextProperty("applicationDirPath", os.fspath(CURRENT_DIRECTORY))
    context.setContextProperty("managerModel", manager)

    filename = os.fspath(CURRENT_DIRECTORY / "main.qml")
    url = QUrl.fromLocalFile(filename)

    def handle_object_created(obj, obj_url):
        if obj is None and url == obj_url:
            QCoreApplication.exit(-1)

    engine.objectCreated.connect(handle_object_created, Qt.QueuedConnection)
    engine.load(url)

    sys.exit(app.exec())


if __name__ == "__main__":
    main()
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

ApplicationWindow {
    width: 640
    height: 480
    visible: true

    ColumnLayout {
        anchors.centerIn: parent

        Repeater {
            id: repeater

            model: managerModel.models

            ComboBox {
                model: modelData
                textRole: "display"
                Layout.fillWidth: true
            }

        }

    }

}

Side note: A QAbstractListModel is a QObject so the double inherence is useless so you should change it to: class Model(QAbstractListModel):

eyllanesc
  • 235,170
  • 19
  • 170
  • 241