Search code examples
pythonpyside2qtreewidgetqtreewidgetitem

QTreeWidgetItem.insertChild at index 0


I am trying to insert a new child item at the top of the group of items. The index value does not seem to be honored and the item goes to the end of the list. I searched and did not find many hits for this type of operation in QTreeWidgets. I did find a simple program with which to experiment:

"""
simple test of treewidget
"""
import sys
from PySide2 import QtWidgets

class Testclass():
    """
    test
    """
    def __init__(self):
        """
        test
        """
        app = QtWidgets.QApplication(sys.argv)
        window = QtWidgets.QWidget()
        layout = QtWidgets.QVBoxLayout(window)

        trw = QtWidgets.QTreeWidget()
        trw.setHeaderLabels(['Name', 'Date', 'Cost ($)'])
        chg = QtWidgets.QTreeWidgetItem(trw, ['carrots', None, None])
        datrows = [[None, '2020-00-00', '0.33'],
                   [None, '2020-00-00', '0.35'],
                   [None, '2020-00-00', '0.36']]
        for datrow in datrows:
            __ = QtWidgets.QTreeWidgetItem(chg, datrow)
        __ = chg.insertChild(0, QtWidgets.QTreeWidgetItem(chg, [None, '2020-00-00', '0.30']))


        layout.addWidget(trw)
        window.show()
        sys.exit(app.exec_())

Testclass()

I played with changing the parent references in the tree widget item, changing the index. It added a blank item and then the new item at the end. The only what I got the desired effect was to fetch all the items, add the new item to the top of the list and rebuild the tree:

"""
simple test of treewidget
"""
import sys
from PySide2 import QtWidgets

class Testclass():
    """
    test
    """
    def __init__(self):
        """
        test
        """
        app = QtWidgets.QApplication(sys.argv)
        window = QtWidgets.QWidget()
        layout = QtWidgets.QVBoxLayout(window)

        trw = QtWidgets.QTreeWidget()
        trw.setHeaderLabels(['Name', 'Date', 'Cost ($)'])
        chg = QtWidgets.QTreeWidgetItem(trw, ['carrots', None, None])
        datrows = [[None, '2020-00-00', '0.33'],
                   [None, '2020-00-00', '0.35'],
                   [None, '2020-00-00', '0.36']]
        for datrow in datrows:
            __ = QtWidgets.QTreeWidgetItem(chg, datrow)
        chi_list = []
        for chgiix, chgii in enumerate(QtWidgets.QTreeWidgetItemIterator(chg)):
            chg_item = chgii.value()
            if chgiix:
                coldata = []
                for colix in range(chg_item.columnCount()):
                    coldata.append(chg_item.text(colix))
                chi_list.append(coldata)
        chi_list.insert(0, [None, '2020-00-00', '0.30'])
        _ = trw.takeTopLevelItem(0)
        chg = QtWidgets.QTreeWidgetItem(trw, ['carrots', None, None])
        for datrow in chi_list:
            __ = QtWidgets.QTreeWidgetItem(chg, datrow)
        print(chi_list)
        layout.addWidget(trw)
        window.show()
        sys.exit(app.exec_())

Testclass()

Is there a better way to do this?


Solution

  • The problem is that you are using the wrong constructor, for example according to your code you are using this constructor:

    QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, const QStringList &strings, int type = Type)
    Constructs a tree widget item and append it to the given parent. The given list of strings will be set as the item text for each column in the item.

    That is, with QtWidgets.QTreeWidgetItem(chg, [None, '2020-00-00', '0.30']) you are already appending the item as a child of the "chg".

    And then as the insertChild() point out:

    void QTreeWidgetItem::insertChild(int index, QTreeWidgetItem *child)
    Inserts the child item at index in the list of children.

    If the child has already been inserted somewhere else it won't be inserted again.

    (emphasis mine)

    That is, being the child of "chg" then it will not be inserted at the beginning.

    The solution is not to pass "chg" but to use this other constructor:

    QTreeWidgetItem::QTreeWidgetItem(const QStringList &strings, int type = Type)
    Constructs a tree widget item of the specified type. The item must be inserted into a tree widget. The given list of strings will be set as the item text for each column in the item.

    import sys
    from PySide2 import QtWidgets
    
    
    class Testclass:
        def __init__(self):
            app = QtWidgets.QApplication(sys.argv)
            window = QtWidgets.QWidget()
            layout = QtWidgets.QVBoxLayout(window)
    
            trw = QtWidgets.QTreeWidget()
            trw.setHeaderLabels(["Name", "Date", "Cost ($)"])
            chg = QtWidgets.QTreeWidgetItem(trw, ["carrots", None, None])
            datrows = [
                [None, "2020-00-00", "0.33"],
                [None, "2020-00-00", "0.35"],
                [None, "2020-00-00", "0.36"],
            ]
            for datrow in datrows:
                QtWidgets.QTreeWidgetItem(chg, datrow)
            chg.insertChild(0, QtWidgets.QTreeWidgetItem([None, "2020-00-00", "0.30"]))
    
            layout.addWidget(trw)
            window.show()
            sys.exit(app.exec_())
    
    
    Testclass()