python - Adding checkBox as vertical header in QtableView -


i trying have qtableview of checkboxes, can use them row selections... have managed that, want header checkbox can check/uncheck or row . have been looking days, couldn't it.

i tried use setheaderdata model, couldn't it. appreciated.

i wasn't particularly happy c++ version @tmoreau ported python didn't:

  • handle more 1 column
  • handle custom header heights (for example multi-line header text)
  • use tri-state checkbox
  • work sorting

so fixed of issues, , created example qstandarditemmodel advocate on trying create own model based on qabstracttablemodel.

there still imperfections, welcome suggestions how improve it!

import sys pyqt4 import qtcore, qtgui   # header supporting checkboxes left of text of subset of columns # subset of columns specified list of column_indices @  # instantiation time class checkboxheader(qtgui.qheaderview):     clicked=qtcore.pyqtsignal(int, bool)      _x_offset = 3     _y_offset = 0 # value calculated later, based on height of paint rect     _width = 20     _height = 20      def __init__(self, column_indices, orientation = qtcore.qt.horizontal, parent = none):         super(checkboxheader, self).__init__(orientation, parent)         self.setresizemode(qtgui.qheaderview.stretch)         self.setclickable(true)          if isinstance(column_indices, list) or isinstance(column_indices, tuple):             self.column_indices = column_indices         elif isinstance(column_indices, (int, long)):             self.column_indices = [column_indices]         else:             raise runtimeerror('column_indices must list, tuple or integer')          self.ischecked = {}         column in self.column_indices:             self.ischecked[column] = 0      def paintsection(self, painter, rect, logicalindex):         painter.save()         super(checkboxheader, self).paintsection(painter, rect, logicalindex)         painter.restore()          #         self._y_offset = int((rect.height()-self._width)/2.)          if logicalindex in self.column_indices:             option = qtgui.qstyleoptionbutton()             option.rect = qtcore.qrect(rect.x() + self._x_offset, rect.y() + self._y_offset, self._width, self._height)             option.state = qtgui.qstyle.state_enabled | qtgui.qstyle.state_active             if self.ischecked[logicalindex] == 2:                 option.state |= qtgui.qstyle.state_nochange             elif self.ischecked[logicalindex]:                 option.state |= qtgui.qstyle.state_on             else:                 option.state |= qtgui.qstyle.state_off              self.style().drawcontrol(qtgui.qstyle.ce_checkbox,option,painter)      def updatecheckstate(self, index, state):         self.ischecked[index] = state         self.viewport().update()      def mousepressevent(self, event):         index = self.logicalindexat(event.pos())         if 0 <= index < self.count():             x = self.sectionposition(index)             if x + self._x_offset < event.pos().x() < x + self._x_offset + self._width , self._y_offset < event.pos().y() < self._y_offset + self._height:                 if self.ischecked[index] == 1:                     self.ischecked[index] = 0                 else:                     self.ischecked[index] = 1                  self.clicked.emit(index, self.ischecked[index])                 self.viewport().update()             else:                 super(checkboxheader, self).mousepressevent(event)         else:             super(checkboxheader, self).mousepressevent(event)  if __name__=='__main__':      def updatemodel(index, state):         in range(model.rowcount()):             item = model.item(i, index)             item.setcheckstate(qtcore.qt.checked if state else qtcore.qt.unchecked)      def modelchanged():         in range(model.columncount()):             checked = 0             unchecked = 0             j in range(model.rowcount()):                 if model.item(j,i).checkstate() == qtcore.qt.checked:                     checked += 1                 elif model.item(j,i).checkstate() == qtcore.qt.unchecked:                     unchecked += 1              if checked , unchecked:                 header.updatecheckstate(i, 2)             elif checked:                 header.updatecheckstate(i, 1)             else:                 header.updatecheckstate(i, 0)      app = qtgui.qapplication(sys.argv)      tableview = qtgui.qtableview()     model = qtgui.qstandarditemmodel()     model.itemchanged.connect(modelchanged)     model.sethorizontalheaderlabels(['title 1\na second line','title 2'])     header = checkboxheader([0,1], parent = tableview)     header.clicked.connect(updatemodel)      # populate models items     in range(3):         item1 = qtgui.qstandarditem('item %d'%i)         item1.setcheckable(true)          item2 = qtgui.qstandarditem('another checkbox %d'%i)         item2.setcheckable(true)          model.appendrow([item1, item2])       tableview.setmodel(model)     tableview.sethorizontalheader(header)     tableview.setsortingenabled(true)     tableview.show()      sys.exit(app.exec_()) 

Comments

Popular posts from this blog

How to connect android app to App engine -

gcc - MinGW's ld cannot perform PE operations on non PE output file -

php - display validation error message next to the textbox in codeigniter -