Pyside6, Qtreeview, row selection, how to determine if clicked was a parent or child
-
I created some python code to present my data in as a QTreeView and the data presentation works great:
I circled an expanded node in red (see pic) And what I'd like to do is determine in the code if the user has clicked on the parent 800000-105 row, or the child row SAMSUNG CL10A....
I hooked the selectionModel signal and it gives me the the data in the first column (regardless of whether its a parent or child node). Here is the code for that:
self._treeview.setModel(self._standard_model) selection = self._treeview.selectionModel() selection.selectionChanged.connect(self._handle_selected)
This the the code handle_selected method:
def _handle_selected(self): for index in self._treeview.selectionModel().selectedRows(): print(f"Row {index.row()} has been selected") print(f"Part number: {index.data()}")
If I click on the parent I get the parents index and the data for the first column:
Row 5 has been selected
Part number: 800000-105If I click on the child column I get the child index, and the data for the first column:
Row 0 has been selected
Part number: SamsungThe problem is, I need to have some way of determining whether the row index number belongs to the parent or child.
There doesn't seem to be a method to determine what level you are at in the heirarchy in the docs. How doe you go about determining what type of node you are dealing with?Complete code listing is attached below:
import sys import pprint from PySide6 import Qt from PySide6.QtWidgets import QApplication,QWidget from PySide6.QtGui import QStandardItemModel from PySide6.QtGui import QStandardItem from PySide6.QtSql import QSqlQuery import config import database from ui.results import Ui_W_SearchResults class Search_PN: def __init__(self, parent, treeview): self._db_obj = database.Database() self._parent = parent self._treeview = treeview self._standard_model = None self._root_node = None def populate(self, search_type): db = self._db_connect() res = False # Determine the type of search to perform everything = "SELECT * FROM PNDesc ORDER BY PartNumber" query = QSqlQuery(db=db) if search_type: if search_type["type"] == "all": res = query.prepare(everything) elif search_type["type"] == "specific": if search_type["criteria"] == "like": # contains # query_string = f"SELECT * FROM PNDesc WHERE PartNumber LIKE '{key}' ORDER BY PartNumber" res = query.prepare("SELECT * FROM PNDesc WHERE PartNumber LIKE :PartNumber ORDER BY PartNumber") if res: query.bindValue(":PartNumber", search_type['key']) elif search_type["criteria"] == "explicit": # explicit (exact match) # query_string = f"SELECT * FROM PNDesc WHERE PartNumber='{key}' ORDER BY PartNumber" res = query.prepare("SELECT * FROM PNDesc WHERE PartNumber=:PartNumber ORDER BY PartNumber") if res: query.bindValue(":PartNumber", search_type['key']) else: # Unknown criteria return False else: # Unknown type return False # Get PNDesc table from DB if res: res = query.exec() if not res: return False # Create standard model self._standard_model = QStandardItemModel(self._parent) # Set root header names self._standard_model.setHorizontalHeaderLabels(["Part Number", "Description"]) # set root node self._root_node = self._standard_model.invisibleRootItem() # Build tree data structure while query.next(): # PN search part_number = query.value(0) description = query.value(1) pn_desc_row = [QStandardItem(part_number), QStandardItem(description)] # Append part number description row to root node self._root_node.appendRow(pn_desc_row) # check for existence of pnmpn row(s) query_pn_mpn = QSqlQuery(query="SELECT * FROM pnmpn WHERE PartNumber='{}'".format(part_number), db=db) while query_pn_mpn.next(): manufacturer_key = query_pn_mpn.value(1) mpn = query_pn_mpn.value(2) # Look up manufacturer from manufacturer key manufacturer = self._get_mfgr_from_id(manufacturer_key, db) manuf_mpn_sub_row = [QStandardItem(manufacturer), QStandardItem(mpn)] # Add mpn/manufacturer child pn_desc_row[0].appendRow(manuf_mpn_sub_row) # Give Treeview the model self._treeview.setModel(self._standard_model) selection = self._treeview.selectionModel() selection.selectionChanged.connect(self._handle_selected) # Set the column sizes self._treeview.setColumnWidth(0, 200) self._treeview.setColumnWidth(1, 500) return True def _handle_selected(self): for index in self._treeview.selectionModel().selectedRows(): print(f"Row {index.row()} has been selected") print(f"Part number: {index.data()}") def _get_mfgr_from_id(self, mfg_key, db): query_string = "SELECT * FROM mlist WHERE MFGId='{}'".format(mfg_key) manufacturer = None query_manufacturer = ( QSqlQuery(query=query_string, db=db)) while query_manufacturer.first(): manufacturer = query_manufacturer.value(1) break return manufacturer def _get_desc_from_pn(self, pn, db): query_string = "SELECT * FROM pndesc WHERE PartNumber='{}'".format(pn) desc = None query_desc = ( QSqlQuery(query=query_string, db=db)) while query_desc.first(): desc = query_desc.value(1) break return desc def _db_connect(self): return self._db_obj.connect(db_name=config.conf.db_name, db_path=config.conf.db_path) if __name__ == "__main__": class TestMainWindow(QWidget, Ui_W_SearchResults): def __init__(self, parent=None): super().__init__(parent) self.setupUi(self) app = QApplication(sys.argv) window = TestMainWindow(None) search = Search_PN(window, window.TV_SearchResults) search_type = {"type": "all", "criteria": "like", "key": "%8001%"} search.populate(search_type) window.show() sys.exit(app.exec())
-
@hwstar said in Pyside6, Qtreeview, row selection, how to determine if clicked was a parent or child:
The problem is, I need to have some way of determining whether the row index number belongs to the parent or child.
There doesn't seem to be a method to determine what level you are at in the heirarchy in the docs.selectedRows()
or any other similar returns a (list of)QModelIndex
. And in addition to arow()
&column()
that always has aparent()
, which is also aQModelIndex
. In a flatQTableModel
that is always an empty/invalidQModelIndex()
, and you can just ignore it/not bother to look at it. But in a hierarchicalQTreeModel
you must always look at it, and that is what tells you where in the hierarchy you are (since e.g. the same row number is used in many distinct rows with the parent differing). Top level items have a parent ofQModelIndex()
or some "root" item (I forget which), so that is how you know to stop recursing.