Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Pyside6, Qtreeview, row selection, how to determine if clicked was a parent or child
Forum Updated to NodeBB v4.3 + New Features

Pyside6, Qtreeview, row selection, how to determine if clicked was a parent or child

Scheduled Pinned Locked Moved Unsolved Qt for Python
3 Posts 2 Posters 1.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • H Offline
    H Offline
    hwstar
    wrote on last edited by
    #1

    I created some python code to present my data in as a QTreeView and the data presentation works great:
    Treeview.png

    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-105

    If 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: Samsung

    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. 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())
    
    JonBJ 1 Reply Last reply
    0
    • H hwstar

      I created some python code to present my data in as a QTreeView and the data presentation works great:
      Treeview.png

      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-105

      If 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: Samsung

      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. 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())
      
      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @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 a row() & column() that always has a parent(), which is also a QModelIndex. In a flat QTableModel that is always an empty/invalid QModelIndex(), and you can just ignore it/not bother to look at it. But in a hierarchical QTreeModel 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 of QModelIndex() or some "root" item (I forget which), so that is how you know to stop recursing.

      1 Reply Last reply
      2
      • H Offline
        H Offline
        hwstar
        wrote on last edited by
        #3

        That works. If the parent has row() and column() values of -1, then that indicates the parent is the root node.

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved