Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Language Bindings
  4. Use delegates to map button's checked-state to a model's boolean?
Forum Updated to NodeBB v4.3 + New Features

Use delegates to map button's checked-state to a model's boolean?

Scheduled Pinned Locked Moved Language Bindings
3 Posts 2 Posters 2.4k Views 1 Watching
  • 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.
  • A Offline
    A Offline
    Alabaster
    wrote on last edited by
    #1

    I've been reading/experimenting with the documentation re: delegates & mapping, but I have been unsuccessful adapting it to my situation. I'd like to map the checked-state of a button to a model's bool value. Basically I'd like to eliminate the "update" method from the code below, and have delegates take care of the mapping automatically. Is this even possible? Thanks

    @
    import sys
    from PySide.QtCore import *
    from PySide.QtGui import *
    from PySide.QtSql import *

    class CentralWidget(QWidget):
    def init(self, mainWindow):
    super(CentralWidget, self).init()
    self.setFixedSize(600,400)

        self.vbox = QVBoxLayout()
        self.contentHBox = QHBoxLayout()
        self.widgetGrid = QGridLayout()
    
        self.createDatabase()
        
        self.model = QSqlTableModel()
        self.model.setTable("NeverGonna")
        self.model.dataChanged.connect(lambda: self.update(thingToChange='buttons'))
        self.model.select()
    
        self.buttonDict = {}
        
        self.createWidgets()
    
        self.update(thingToChange='buttons')
        
        self.confirmButton = QPushButton("Show/Hide Results")
        self.confirmButton.clicked.connect(self.confirmResults)
        
        self.view = QTableView()
        self.view.setModel(self.model)
        self.view.hide()
    
        self.contentHBox.addLayout(self.widgetGrid)
        self.contentHBox.addStretch(1)
        
        self.vbox.addLayout(self.contentHBox)
        self.vbox.addWidget(self.confirmButton)
        self.vbox.addWidget(self.view)
        self.vbox.addStretch(1)
    
        self.setLayout(self.vbox)
    
    def createWidgets(self):
        for r in range(self.model.rowCount()):
            rec = self.model.record(r)
            name = rec.value(0)
    
            newLabel = QLabel(name)
            text = QLabel("... is gonna")
    
            self.buttonList=[]
    
            b1Text = self.model.headerData(1, Qt.Horizontal, Qt.DisplayRole)
            b2Text = self.model.headerData(2, Qt.Horizontal, Qt.DisplayRole)
            b3Text = self.model.headerData(3, Qt.Horizontal, Qt.DisplayRole)
    
            button1 = QPushButton(b1Text)
            button2 = QPushButton(b2Text)
            button3 = QPushButton(b3Text)
    
            button1.setCheckable(True)
            button2.setCheckable(True)
            button3.setCheckable(True)
    
            button1.clicked.connect(lambda: self.update(thingToChange='model'))
            button2.clicked.connect(lambda: self.update(thingToChange='model'))
            button3.clicked.connect(lambda: self.update(thingToChange='model'))
    
            self.buttonDict[name] = { b1Text : button1,
                                      b2Text : button2,
                                      b3Text : button3}
    
            self.widgetGrid.addWidget(newLabel, r,0)
            self.widgetGrid.addWidget(text, r, 1)
            self.widgetGrid.addWidget(button1, r,2)
            self.widgetGrid.addWidget(button2, r,3)
            self.widgetGrid.addWidget(button3, r,4)
    
    def update(self, thingToChange='buttons'):
        print("update")
        keyList = sorted(self.buttonDict.keys())
    
        for index, person in enumerate(keyList):
    
            num = index
            for header in self.buttonDict[person].keys():
                button = self.buttonDict[person][header]
    
                if thingToChange == 'buttons':
                    #self.model.select()
                    button.blockSignals(True)
                    if int(self.model.record(num).value(header)) == 1:
                        button.setChecked(True)
                        print("checking button {0} - {1}".format(person, header))
                    else:
                        button.setChecked(False)
                        print("UNchecking button {0} - {1}".format(person, header))
                    button.blockSignals(False)
    
                elif thingToChange == 'model':
                    if button.isChecked():
                        print('Updating Model: {0} - {1} = TRUE (1)'.format(person, header))
                        query = QSqlQuery("UPDATE NeverGonna SET '{h}'='1' WHERE Name='{n}'".format(h=header, n=person))
                    else:
                        print('Updating Model: {0} - {1} = FALSE (0)'.format(person, header))
                        query = QSqlQuery("UPDATE NeverGonna SET '{h}'='0' WHERE Name='{n}'".format(h=header, n=person))
    
                    self.model.select()
                else:   return
    
    def confirmResults(self):
        if self.view.isVisible():
            self.view.hide()
        else:
            self.view.show()
    
    def createDatabase(self):
        db = QSqlDatabase.addDatabase("QSQLITE")
        db.setDatabaseName("ForumQuestionDelegates")
        ok = db.open()
        print(ok)
        query = QSqlQuery("DROP TABLE IF EXISTS NeverGonna")
        query = QSqlQuery("CREATE TABLE NeverGonna (Name VARCHAR(20), GiveYouUp BOOL, LetYouDown BOOL, RunAroundAndDesertYou BOOL)")
        query = QSqlQuery("INSERT INTO NeverGonna (Name, GiveYouUp, LetYouDown, RunAroundAndDesertYou) VALUES('01 - Rick Astley', '0',' 0', '0')")
        query = QSqlQuery("INSERT INTO NeverGonna (Name, GiveYouUp, LetYouDown, RunAroundAndDesertYou)  VALUES('02 - Mick Nastley', '1', '1', '1')")
    

    class MainWindow(QMainWindow):
    def init(self):
    super(MainWindow, self).init()

        self.centralWidget = CentralWidget(self)
    
        self.setCentralWidget(self.centralWidget)
        self.setWindowTitle("Can I use delegates to map button checked-state to model's 'bools' (1/0)?")
        self.show()
    

    def main():
    app = QApplication(sys.argv)
    win = MainWindow()
    app.setStyle('cleanlooks')
    sys.exit(app.exec_())

    if name == 'main':
    main()
    @

    1 Reply Last reply
    0
    • jazzycamelJ Offline
      jazzycamelJ Offline
      jazzycamel
      wrote on last edited by
      #2

      Hi Alabaster,

      The following is an example I developed a while back for my students which contains two QTableView's with the same model. The first column of each has a button delegate which reflects the boolean status of the associated model index, i.e. checking a button in one table will cause the corresponding button in the other table to also be checked. The code is written for PyQt4 rather than PySide but it shouldn't take too much thought/effort to convert it.

      @
      import sip
      sip.setapi('QString', 2)
      sip.setapi('QVariant', 2)

      from PyQt4.QtCore import *
      from PyQt4.QtGui import *

      class TableModel(QAbstractTableModel):
      def init(self, parent=None, **kwargs):
      QAbstractTableModel.init(self, parent, **kwargs)

          self._data=[[False for _ in xrange(10)] for _ in xrange(10)]
      
      def rowCount(self, parent=QModelIndex()): return len(self._data)
      def columnCount(self, parent=QModelIndex()): return len(self._data[0])
      
      def data(self, index, role=Qt.DisplayRole):
          if not index.isValid(): return None
          if not role==Qt.DisplayRole: return None
      
          return self._data[index.row()][index.column()]
      
      def setData(self, index, value, role=Qt.EditRole):
          if not index.isValid(): return False
          if not role==Qt.EditRole: return False
      
          self._data[index.row()][index.column()]=value
          self.dataChanged.emit(index, index)
          return True
      

      class ButtonDelegate(QItemDelegate):
      def init(self, parent):
      QItemDelegate.init(self, parent)

          self._editors={}
          self._model=None
      
      def paint(self, painter, option, index):
          if self._model==None:
              self._model=self.parent().model()
              self._model.dataChanged.connect(self._modelChanged)
      
          if not self.parent().indexWidget(index):
              row,column=index.row(),index.column()
              button=QPushButton(
                      "({0},{1})".format(row,column),
                      self.parent(), 
                      clicked=lambda: self._setModelData(row, column),
                      checkable=True
                  )
      
              self.parent().setIndexWidget(index, button)
              self._editors[(row,column)]=button
      
      def _setModelData(self, row, column):
          button=self._editors[(row,column)]
          model=self.parent().model()
          index=model.index(row,column)
          model.setData(index, button.isChecked())
      
      @pyqtSlot(QModelIndex,QModelIndex)
      def _modelChanged(self, start, end):
          row,column=start.row(),start.column()
          checked=start.data()
          if checked==self._editors[(row,column)].isChecked(): return
          self._editors[(row,column)].setChecked(checked)
      

      class TableView(QTableView):
      def init(self, *args, **kwargs):
      QTableView.init(self, *args, **kwargs)

          self.setItemDelegateForColumn(0, ButtonDelegate(self))
      

      if name=="main":
      from sys import argv, exit

      class Widget(QWidget):
          def __init__(self, parent=None):
              QWidget.__init__(self, parent)
      
              l=QVBoxLayout(self)
      
              self._tm=TableModel(self)
      
              self._tv=TableView(self)
              self._tv.setModel(self._tm)
              l.addWidget(self._tv)
      
              self._tv2=TableView(self)
              self._tv2.setModel(self._tm)
              l.addWidget(self._tv2)
      
      a=QApplication(argv)
      w=Widget()
      w.show()
      w.raise_()
      exit(a.exec_())
      

      @

      I hope this helps with your problem ;o)

      For the avoidance of doubt:

      1. All my code samples (C++ or Python) are tested before posting
      2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
      1 Reply Last reply
      0
      • A Offline
        A Offline
        Alabaster
        wrote on last edited by
        #3

        Thanks for the response -- I'll have to do some translating to PySideify it but I think that's doable. I'll post back if I'm still confused.

        Thanks!

        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