Create a tree using threads

I am trying to create an application that will be getting data through an API and present them in QTreeView, using PySide6. As it takes a long time to get the data I want to retrieve them using a QThread. My example code is the following:

import logging
import time

from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *

logging.basicConfig(
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    level=logging.INFO)

class MainWindow(QMainWindow):
    gettingData = False
    counting = False


    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.counter = 0

        layout = QVBoxLayout()


        self.b = QPushButton("Start Counting with a Thread")
        self.bt1 = QPushButton("Generate tree with Thread")
        self.bt2 = QPushButton("Generate tree without a Thread")
        self.tree = QTreeView()

        layout.addWidget(self.b)
        layout.addWidget(self.bt1)
        layout.addWidget(self.bt2)
        layout.addWidget(self.tree)
        self.b.clicked.connect(self.startCounting)
        self.bt1.clicked.connect(self.startGenerating)
        self.bt2.clicked.connect(self.startGenerating2)

        w = QWidget()
        w.setLayout(layout)

        self.setCentralWidget(w)

        self.show()

        self.threadpool = QThreadPool()
        print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount())

    def startCounting(self):
        thread = Thread(self.counting)
        thread.signal.signal.connect(self.something)
        self.threadpool.start(thread)

    def something(self, signal):
        if signal == "False":
            logging.info("Counting is Complete")
        else:
            logging.info(signal)

    def startGenerating(self):
        thread = DataThread()
        thread.signals.signal_QStandardItemModel(self.treeAction)
        self.threadpool.start(thread)

    def treeAction(self,signal):
        self.tree.setModel(signal)

    def startGenerating2(self):
        start = time.perf_counter()
        siteTreeViewModel = QStandardItemModel()
        rootNode = siteTreeViewModel.invisibleRootItem()
        aItem = TreeStandardItem("A")
        bItem = TreeStandardItem("B")
        cItem = TreeStandardItem("C")
        rootNode.appendRow(aItem)
        time.sleep(3)
        rootNode.appendRow(bItem)
        time.sleep(3)
        bItem.appendRow(cItem)
        self.tree.setModel(siteTreeViewModel) 
        end = time.perf_counter() - start
        logging.info("Generated tree in "+str(end))     



class Thread(QRunnable):

    def __init__(self, counting):
        super(Thread, self).__init__()
        self.counting = counting
        self.signal = Signal()

    def run(self):
        for x in range(10):
            self.signal.signal.emit(str(x))
            time.sleep(.1)
        counting = False
        self.signal.signal.emit(str(counting))

class Signal(QObject):
    signal = Signal(str)

class DataThread(QRunnable):

    def __init__(self):
        super(DataThread, self).__init__()
        self.signals = WorkerSignals()

    def run(self):
        logging.info("Start generating the tree")

        start = time.perf_counter()
        siteTreeViewModel = QStandardItemModel()
        rootNode = siteTreeViewModel.invisibleRootItem()
        aItem = TreeStandardItem("A")
        bItem = TreeStandardItem("B")
        cItem = TreeStandardItem("C")
        rootNode.appendRow(aItem)
        time.sleep(2)
        rootNode.appendRow(bItem)
        time.sleep(2)
        bItem.appendRow(cItem)
        end = time.perf_counter() - start
        self.signals.signal_QStandardItemModel.emit(siteTreeViewModel)
        logging.info("Generated tree in "+str(end))
        self.signals.finished.emit()

class TreeStandardItem(QStandardItem):
    def __init__(self, txt=''):
        super().__init__()
        self.setEditable = False
        self.setForeground(QColor(255, 255, 255))
        self.setText(txt)

class WorkerSignals(QObject):
    signal_QStandardItemModel = Signal()
    finished = Signal()

app = QApplication([])
window = MainWindow()
app.exec()

The first counting button works as expected creating a thread. Generating the tree without a thread, confirms that the code I am trying to run using a thread is working Once I try running the tree generation using thread, I get the following error:

Traceback (most recent call last):
  File "/home/giunz/code/tutorial/threaded-tree-01.py", line 61, in startGenerating
    thread.signals.signal_QStandardItemModel(self.treeAction)
TypeError: 'Signal' object is not callable

Any help on how to generate the tree using a thread, would be appreciated.

Thanks in advance

Traceback (most recent call last):
  File "/home/giunz/code/tutorial/threaded-tree-01.py", line 61, in startGenerating
    thread.signals.signal_QStandardItemModel(self.treeAction)
TypeError: 'Signal' object is not callable

This error is telling you that you’re attempting to call an object which isn’t a method or function (i.e. a callable). What I think you’re looking for is .connect() which is what you use to connect a signal to a given target, e.g.

thread.signals.signal_QStandardItemModel.connect(self.treeAction)