title: background color of cells in QTableview, PySide2
body: <p>Is it possible to conditionally change the background color of items in a QTableView, using PySide2? 
  I've read a lot on the <a href="https://doc.qt.io/qt-5/model-view-programming.html#the-model-view-classes" rel="nofollow noreferrer">model view framework</a> . I cannot figure out if it is necessary to use a Delegate or not. Recently I was able to get a column of checkboxes without a Delegate. I believe that the virtual methods <code>setItemData(index, roles)</code> and <code>itemData(index)</code> could be what I need. However, there is no <code>QMap</code> in PySide2. My model must need somewhere to store the extra information to be used by <code>QtCore.Qt.BackgroundRole</code> (that enum, btw, says "the background brush used for items rendered with the default delegate") If I don't specify a delegate, is the "default delegate" used?. Should I be using <code>QStandardItemModel</code> instead?
  In the example code below, how would I get a particular column's background color to be red based on some thresholds (the min and max column are the thresholds? </p>
  
  <pre><code>from PySide2.QtWidgets import (QWidget, QApplication, QTableView,QVBoxLayout)
  import sys
  from PandasModel2 import  PandasModel2
  import numpy as np
  import pandas as pd
  class Example(QWidget):
      def __init__(self):
          super().__init__()
          self.setGeometry(300, 300, 700, 300)
          self.setWindowTitle("QTableView")
          self.initData()
          self.initUI()
  
      def initData(self):
  
          data = pd.DataFrame(np.random.randint(1,10,size=(6,4)), columns=['Test#','MIN', 'MAX','MEASURED'])
          data['Test#'] = [1,2,3,4,5,6]                    
          #add the checkable column to the DataFrame
          data['Check'] = True
          self.model = PandasModel2(data)
  
      def initUI(self):
          self.tv = QTableView(self)
          self.tv.setModel(self.model)
          vbox = QVBoxLayout()
          vbox.addWidget(self.tv) 
          self.setLayout(vbox)  
  
  app = QApplication([])
  ex = Example()
  ex.show()
  sys.exit(app.exec_())
  </code></pre>
  
  <p>And I have a custom model using a pandas dataFrame:</p>
  
  <pre><code>import PySide2.QtCore as QtCore
  class PandasModel2(QtCore.QAbstractTableModel):
      """
      Class to populate a table view with a pandas dataframe.
      This model is non-hierachical. 
      """
      def __init__(self, data, parent=None):
          QtCore.QAbstractTableModel.__init__(self, parent)
          self._data = data
  
      def rowCount(self, parent=None):
          return self._data.shape[0]
  
      def columnCount(self, parent=None):
          return self._data.shape[1]
  
      def data(self, index, role=QtCore.Qt.DisplayRole):
          if role==QtCore.Qt.DisplayRole:
              if index.column() != 4: 
              #don't want what determines check state to be shown as a string
                  if index.isValid():              
                      if index.column() in [1,2,3]:
                          return '{:.3f}'.format(self._data.iloc[index.row(), index.column()])    
                      if index.column() == 0:
                          return '{:.2f}'.format(self._data.iloc[index.row(), index.column()])
                      return str(self._data.iloc[index.row(), index.column()])
          if role==QtCore.Qt.CheckStateRole:  
              if index.column()==4:#had to add this check to get the check boxes only in column 10
                  if self._data.iloc[index.row(), index.column()] == True:
                      return QtCore.Qt.Checked
                  else:
                     return QtCore.Qt.Unchecked
  
      def getMinimum(self, row):
          return self._data.iloc[row, self.getColumnNumber('MIN')]
      def getMaximum(self, row):
          return self._data.iloc[row, self.getColumnNumber('MAX')]
  
      def getColumnNumber(self, string):
          '''
          Given a string that identifies a label/column, 
          return the location of that label/column.
          This enables the config file columns to be moved around. 
          '''
          return self._data.columns.get_loc(string)
  
      def headerData(self, col, orientation, role):
          if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
              return self._data.columns[col]
          return None
      def flags(self, index):
          '''
          The returned enums indicate which columns are editable, selectable, 
          checkable, etc. 
          The index is a QModelIndex. 
          '''
          if index.column() == self.getColumnNumber('Check'):
              #print(index.column())
              return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsUserCheckable
          else:
              return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsEditable
          return QtCore.Qt.ItemIsEnabled
  
      def setData(self, index, value, role=QtCore.Qt.DisplayRole):
          """Set the value to the index position depending on Qt::ItemDataRole and data type of the column
          Args:
              index (QtCore.QModelIndex): Index to define column and row.
              value (object): new value.
              role (Qt::ItemDataRole): Use this role to specify what you want to do.
          Raises:
              TypeError: If the value could not be converted to a known datatype.
          Returns:
              True if value is changed. Calls layoutChanged after update.
              False if value is not different from original value.
          """
          if not index.isValid(): 
              return False
          if role == QtCore.Qt.DisplayRole: #why not edit role?
              self._data.iat[index.row(),index.column()]= value
              self.layoutChanged.emit()
              return True
          elif role == (QtCore.Qt.CheckStateRole | QtCore.Qt.DisplayRole):
              #this block does get executed when toggling the check boxes, 
              #verified with debugger. Although the action is the same 
              #as the block above! 
              self._data.iat[index.row(),index.column()]= value
              self.layoutChanged.emit()
              return True
          else:
              return False
  </code></pre>