pythonpyqtqstandarditemmodelqstandarditem

PyQt: How to connect a QStandardItem in a QStandardItemModel to a function


I am creating an application in PyQt in which I have a a list of check boxes which I have created using QStandardItemModel and QStandardItem and it works perfectly. I want to connect the first item in the list which is a 'Select all' check box to a function. This function should be able to check all the other items of the list. I'm trying to do this by the following code:

    model = QStandardItemModel(list)  
    item = QStandardItem("Select all")
    model.appendRow(item)                  
    item.setCheckable(True)
    model.itemChanged.connect(state_changed)

    def state_changed(item):
         print ("Hello")

I have added more items to the list from the output of an SQL query and I can see that 'Hello' is printed irrespective of which check box I click. This is my entire code:

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtSql import *
def main():  
    db = QSqlDatabase.addDatabase("QODBC") 
    db.setHostName('LAPTOP-B79DRPA3')
    db.setDatabaseName('local')
    db.open()
    if (db.open()==False):     
      QMessageBox.critical(None, "Database Error",
                db.lastError().text())   

    query = QSqlQuery () 
    query.exec_  ("select id from [Sarah].[dbo].fraga")

    list = QListView()
    model = QStandardItemModel(list)  

    item = QStandardItem("Select all")
    model.appendRow(item)                  
    item.setCheckable(True)
    model.itemChanged.connect(state_changed)

    while (query.next()):
        item1 = QStandardItem(str(query.value(0)))
        model.appendRow(item1)                  
        item1.setCheckable(True)   

    list.setModel(model)
    list.show()
    return app.exec_()

def state_changed(item):
    print ("Hello")

if __name__ == '__main__':
    app  = QApplication(sys.argv)
    list = QListView()
    model = QStandardItemModel(list) 
    main()

How do I ensure that the function is invoked only when the state of 'Select All' is changed?


Solution

  • Instead of connecting to QAbstractItemModel.itemChanged signal, connect to QAbstractItemView.clicked signal, which specifies the index clicked. Also, it's advisable not to name a variable list, as it interferes with the built-in list.

    import sys
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    from PyQt4.QtSql import *
    def main():
        db = QSqlDatabase.addDatabase("QODBC")
        db.setHostName('LAPTOP-B79DRPA3')
        db.setDatabaseName('local')
        db.open()
        if (db.open()==False):
          QMessageBox.critical(None, "Database Error",
                    db.lastError().text())
    
        query = QSqlQuery ()
        query.exec_  ("select id from [Sarah].[dbo].fraga")
    
        list_view = QListView()
        model = QStandardItemModel(list_view)
    
        item = QStandardItem("Select all")
        model.appendRow(item)
        item.setCheckable(True)
        list_view.clicked.connect(state_changed)
    
        while (query.next()):
            item1 = QStandardItem(str(query.value(0)))
            model.appendRow(item1)
            item1.setCheckable(True)
    
        list_view.setModel(model)
        list_view.show()
        return app.exec_()
    
    def state_changed(index):
        row = index.row()
        if row == 0:
            print ("Hello")
    
    if __name__ == '__main__':
        app  = QApplication(sys.argv)
        list_view = QListView()
        model = QStandardItemModel(list)
        main()