Results 1 to 3 of 3

Thread: How to filter items of a combobox in tableview and QSqlRelationalTableModel?

  1. #1
    Join Date
    Jun 2021
    Posts
    2
    Qt products
    Platforms
    Unix/X11

    Default How to filter items of a combobox in tableview and QSqlRelationalTableModel?

    Hi everybody. i know this forum is for c++ but as it is related to Qt i asked it here may somebody help.

    I am trying learning PyQt5. I made an app. In my app I have a tableview that is set as below:

    Qt Code:
    1. self.table = QTableView()
    2. self.model = QSqlRelationalTableModel(self)
    3. self.model.setTable('main')
    4. self.model.setEditStrategy(QSqlTableModel.OnFieldChange)
    5. self.model.setRelation(1, QSqlRelation("Names", "nameOfCm", "nameOfCm"))
    6. self.model.setRelation(2, QSqlRelation("Types", "type_IDs", "typeOfCm"))
    7. self.model.setRelation(8, QSqlRelation("Places", "placeName", "placeName"))
    8. self.model.select()
    9. self.table.setModel(self.model)
    10. self.table.setItemDelegate(QSqlRelationalDelegate(self.table))
    To copy to clipboard, switch view to plain text mode 

    By using QSqlRelationalDelegate I have comboboxes in some columns of the table.

    Column No:1 is the name of some electronic components (like Transistor Or IC etc.).

    Column No:2 is the type of this electronic components (For example PNP, NPNOp-Amp, Micro and so on).

    When I click on combobox in column "type"(Column No:2) it shows all type of electronic components no matter what I have selected in combobox column "name" (Column No:1).
    I want to filter these items in such a way that only related items for combobox "name" show in the combobox "type".

    For example If I choose transistor from "name", combobox "type" shows: NPN, PNP.
    And if I choose IC, combobox "type" shows: Micro, Op_Amp.

    what should I do ?

    This is simplified code( you need to ad components by clicking on "add components" button above the table:

    Qt Code:
    1. import sys
    2. from PyQt5.QtCore import Qt
    3. from PyQt5.QtWidgets import *
    4. from PyQt5.QtSql import *
    5.  
    6. connectDB = QSqlDatabase.addDatabase("QSQLITE")
    7. connectDB.setDatabaseName('test.db')
    8. connectDB.open()
    9. query = QSqlQuery()
    10. createNameTable='CREATE TABLE IF NOT EXISTS "Names" ("nameOfCm" TEXT, PRIMARY KEY("nameOfCm"))'
    11. createTypeTable='CREATE TABLE IF NOT EXISTS "Types" ("type_IDs" TEXT, "typeOfCm" TEXT,PRIMARY KEY("type_IDs"))'
    12. createMainTable='CREATE TABLE IF NOT EXISTS "main" ("partnumber" TEXT,"name" TEXT,"type" TEXT,PRIMARY KEY("partnumber"))'
    13.  
    14. query.exec(createNameTable)
    15. query.exec(createTypeTable)
    16. query.exec(createMainTable)
    17. query.exec("INSERT INTO Names (nameOfCm) VALUEs ('IC')")
    18. query.exec("INSERT INTO Names (nameOfCm) VALUEs ('Transistor')")
    19. query.exec("INSERT INTO Types (type_IDs,typeOfCm) VALUEs ('Transistor1','NPN')")
    20. query.exec("INSERT INTO Types (type_IDs,typeOfCm) VALUEs ('Transistor2','PNP')")
    21. query.exec("INSERT INTO Types (type_IDs,typeOfCm) VALUEs ('IC1','Op_AMP')")
    22. query.exec("INSERT INTO Types (type_IDs,typeOfCm) VALUEs ('IC2','Micro')")
    23.  
    24. class main (QMainWindow):
    25. def __init__(self):
    26. super(main,self).__init__()
    27. self.setWindowTitle('My Electronic Inventory v: 0.1')
    28. self.setGeometry(10, 10, 400 , 500)
    29. self.UI()
    30. self.show()
    31. self.databaseIsConect()
    32.  
    33. def UI(self):
    34.  
    35. self.mainCentralWidget = QWidget()
    36. self.mainLayout = QVBoxLayout()
    37. self.setCentralWidget(self.mainCentralWidget)
    38. self.centralWidget().setLayout(self.mainLayout)
    39.  
    40. self.newComponentButton= QPushButton("Add component")
    41. self.newComponentButton.clicked.connect(self.newComponentButtonClicked)
    42.  
    43. self.table= QTableView()
    44. self.model = QSqlRelationalTableModel(self)
    45. self.model.setTable('main')
    46. self.model.setEditStrategy(QSqlTableModel.OnFieldChange)
    47. self.model.setRelation(1, QSqlRelation("Names", "nameOfCm", "nameOfCm"))
    48. self.model.setRelation(2, QSqlRelation("Types", "type_IDs", "typeOfCm"))
    49. self.model.select()
    50. self.table.setModel(self.model)
    51. self.table.setItemDelegate(QSqlRelationalDelegate(self.table))
    52. self.table.setEditTriggers(QAbstractItemView.DoubleClicked|QAbstractItemView.AnyKeyPressed)
    53. self.model.setHeaderData(0,Qt.Horizontal,('Part Number'))
    54. self.model.setHeaderData(1,Qt.Horizontal,('Name'))
    55. self.model.setHeaderData(2,Qt.Horizontal,('Type'))
    56.  
    57. self.mainLayout.addWidget(self.newComponentButton)
    58. self.mainLayout.addWidget(self.table)
    59.  
    60. def databaseIsConect(self):
    61. if connectDB.isOpen():
    62. print("Databsae Is Connected")
    63. else:
    64. print("Erorr!. Databsae Is Not Connected")
    65. def newComponentButtonClicked(self):
    66. row = self.model.rowCount()
    67. self.model.insertRow(row)
    68. if __name__ == '__main__':
    69. app = QApplication(sys.argv)
    70. ex = main()
    71. sys.exit(app.exec_())
    To copy to clipboard, switch view to plain text mode 

    After some try, I managed to solve part of my problem by sub-classing QSqlRelationalTableModel:
    Qt Code:
    1. class mysqlmodel(QSqlRelationalTableModel):
    2. def __init__(self, parent):
    3. super().__init__()
    4.  
    5. def setData(self, item, value, role):
    6.  
    7. super().setData(item,value, role)
    8. a= item.siblingAtColumn(1).data()
    9. self.relationModel(2).setFilter("type_IDs like '"+a+"%'")
    10. return True
    To copy to clipboard, switch view to plain text mode 
    This works for my purpose, but there are issues:

    At first run, if you want to change an item in combobox 2, it shows all options, but after modifications it shows just item belongs to item in combobox 1.
    If you change an item in combobox 2 of row no 2, then you want to change an item in combobox 2 of row 3, it shows options for the "PREVIOUS" row unless you submit that(for example by pressing enter button or clicking somewhere else within the table) and then automatically it changes to options for current row, and now you can select the right item.
    Last edited by yousef; 30th June 2021 at 16:57.

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,229
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How to filter items of a combobox in tableview and QSqlRelationalTableModel?

    i know this forum is for c++ but as it is related to Qt
    The forum is for any Qt-related programming question. Because of Qt's history, most of the Q&A is about C++, but Python + Qt is becoming more popular so questions about PyQt (and other bindings) are welcome.

    I am neither a Python nor SQL expert, so I hope someone can give you an answer.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. #3
    Join Date
    Jun 2021
    Posts
    2
    Qt products
    Platforms
    Unix/X11

    Default Re: How to filter items of a combobox in tableview and QSqlRelationalTableModel?

    Thank you d_stranz

    I found a way. everything work as I expected except one thing. I did this by re implementing QSqlRelationalDelegate as this:
    Qt Code:
    1. class mydelegate(QSqlRelationalDelegate):
    2. def __init__(self, parent=None):
    3. super().__init__()
    4. self.tab=parent
    5.  
    6. def setEditorData(self,editor,index):
    7. if index.column()==2:
    8. test= ((self.tab.selectionModel().currentIndex().siblingAtColumn(1).data()))
    9. editor.model().setFilter("type_IDs like '"+test+"%'")
    10. return super().setEditorData(editor,index)
    To copy to clipboard, switch view to plain text mode 


    the only problem remains is changing an item in column 1 doesn't changes items in column 2 automatically and I have to modify second Column manually else it remains wrong option.
    for example if column 1 be "IC" and Column 2 be "Timer" and then i change column 1 to "Transistor" column 2 remains "Timer" unless I edit that too.

    how to solve this?

Similar Threads

  1. Replies: 0
    Last Post: 14th August 2018, 12:57
  2. Replies: 0
    Last Post: 31st October 2010, 22:55
  3. Combobox entries filter as I type
    By yazwas in forum Qt Programming
    Replies: 3
    Last Post: 8th August 2009, 15:04
  4. QSqlRelationalTableModel and comboBox
    By musti in forum Newbie
    Replies: 9
    Last Post: 14th October 2007, 10:43
  5. Realtime TableView filter with (lineEdit)
    By xgoan in forum Qt Programming
    Replies: 2
    Last Post: 21st December 2006, 16:17

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.