ProfP30
ProfP30

Reputation: 358

store and retrieve data on items/rows in a QTreeView()-Object via QStardItemModel()

I am populating data from a SQLite-Database into a PyQt5 TreeView-control (QTreeView). The data is written via the QStandardItemModel().

Problem: I want to remember the row_id per row, without displaying it. I used to select it in the query but hide the column. But when querying the row_id from the column with index=0, this fails, because it is not visible.

I dont know a.) how to store the row_id in order to b.) retrieve it later on. I want to loop over the selected rows and perform some actions with the according row_id's (e.g. bulk delete, bulk edit, bulk copy etc.)

model.setData always needs an column-index... Qt.UserRole seems to fail on retrieving the data.

Code:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class App(QWidget):
    MAIL_RANGE = 4
    ID, FROM, SUBJECT, DATE = range(MAIL_RANGE)

    def __init__(self):
        super().__init__()      
        self.left = 10
        self.top = 10
        self.width = 640
        self.height = 240
        self.initUI()

        self.dataView.setSelectionMode(QAbstractItemView.ExtendedSelection)  #  <- enable selection of rows in tree
        self.dataView.setEditTriggers(QAbstractItemView.NoEditTriggers)      #  <- disable editing items in tree

        for i in range(0, 2):
            self.dataView.resizeColumnToContents(i)

        self.pbOk = QPushButton(self)
        self.pbOk.setText("Ok")
        self.pbOk.move(400,0)
        self.pbOk.show()

        # connect handlers
        self.dataView.doubleClicked.connect(self.on_dataView_doubleClicked)
        self.pbOk.clicked.connect(self.on_pbOk_clicked)

    def on_dataView_doubleClicked(self):
        print("on_dataView_doubleClicked() called.")

    def on_pbOk_clicked(self):
        print("on_pbOk_clicked() called.")

        # get all IDs
        message: str = ""
        col_ind: int = 0
        for item in self.dataView.selectedIndexes():
            if col_ind % (self.MAIL_RANGE) == 0:  # indicates a row beginning
                text = item.data(Qt.DisplayRole)  # or ix.data()
                message = message + "\n" + str(text)
                self.create_dialog(text)
            col_ind += 1
        print(message)

    def create_dialog(self, id):
        print("dialog called for " + str(id))
        myDlg = QDialog(self)
        lbl = QLabel(myDlg)
        lbl.setText("Hello id: " + str(id))        
        myDlg.show()
        myDlg.resize(300,200)

    def initUI(self):        
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.dataGroupBox = QGroupBox("Inbox")
        self.dataView = QTreeView()
        self.dataView.setRootIsDecorated(False)
        self.dataView.setAlternatingRowColors(True)        

        dataLayout = QHBoxLayout()
        dataLayout.addWidget(self.dataView)
        self.dataGroupBox.setLayout(dataLayout)

        model = self.createMailModel(self)
        self.dataView.setModel(model)
        self.addMail(model, 1, '[email protected]', 'Your Github Donation','03/25/2017 02:05 PM')
        self.addMail(model, 2, '[email protected]', 'Github Projects','02/02/2017 03:05 PM')
        self.addMail(model, 3, '[email protected]', 'Your Phone Bill','01/01/2017 04:05 PM')
        self.addMail(model, 4, '[email protected]', 'aaaYour Github Donation','03/25/2017 02:05 PM')
        self.addMail(model, 5, '[email protected]', 'bbbGithub Projects','02/02/2017 03:05 PM')
        self.addMail(model, 6, '[email protected]', 'cccYour Phone Bill','01/01/2017 04:05 PM')

        self.dataView.setColumnHidden(0, True)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.dataGroupBox)
        self.setLayout(mainLayout)

        self.show()

    def createMailModel(self,parent):
        model = QStandardItemModel(0, self.MAIL_RANGE, parent)
        model.setHeaderData(self.ID, Qt.Horizontal, "ID")
        model.setHeaderData(self.FROM, Qt.Horizontal, "From")
        model.setHeaderData(self.SUBJECT, Qt.Horizontal, "Subject")
        model.setHeaderData(self.DATE, Qt.Horizontal, "Date")
        return model

    def addMail(self, model, mailID, mailFrom, subject, date):
        model.insertRow(0)
        model.setData(model.index(0, self.ID), mailID)
        model.setData(model.index(0, self.FROM), mailFrom)
        model.setData(model.index(0, self.SUBJECT), subject)
        model.setData(model.index(0, self.DATE), date)        

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

Wrap-Up:

1.) On addMail() I would like to add the ID to the inserted row.

2.) On the on_pbOk_clicked() event I want to loop over the selected rows and get all the IDs per the respective row.

If I add the ID as separate column, I cannot retrieve it later, because that's not working on hidden columns.

Upvotes: 3

Views: 2564

Answers (1)

eyllanesc
eyllanesc

Reputation: 243965

As you established that the selection is by rows then it is only necessary to get the row and iterate over it, in this case using set get the selected rows and itero on the columns.

def on_pbOk_clicked(self):
    message: str = ""
    rows = set(ix.row() for ix in self.dataView.selectedIndexes())
    for row in rows:
        values_for_row = []
        for col in range(App.MAIL_RANGE):
            it = self.dataView.model().item(row, col)
            values_for_row.append(it.text())
        text = " ".join(values_for_row)
        self.create_dialog(text)
        message += "\n" + text
    print(message)

Upvotes: 1

Related Questions