code: def data(self, index, role=Qt.DisplayRole):
          
  
          # an index is invalid, if a row or column does not exist or extends
          # the bounds of self.columnCount() or self.rowCount()
          # therefor a check for col>1 is unnecessary.
          if not index.isValid():
              return None
  
          col = index.column()
  
          #row = self._dataFrame.columns[index.column()]
          columnName = self._dataFrame.columns[index.row()]
          columnDtype = self._dataFrame[columnName].dtype
  
          if role == Qt.DisplayRole or role == Qt.EditRole:
              if col == 0:
                  if columnName == index.row():
                      return index.row()
                  return columnName
              elif col == 1:
                  return SupportedDtypes.description(columnDtype)
          elif role == DTYPE_ROLE:
              if col == 1:
                  return columnDtype
              else:
                  return None
docs: Retrieve the data stored in the model at the given `index`.
  
          Args:
              index (QtCore.QModelIndex): The model index, which points at a
                  data object.
              role (Qt.ItemDataRole, optional): Defaults to `Qt.DisplayRole`. You
                  have to use different roles to retrieve different data for an
                  `index`. Accepted roles are `Qt.DisplayRole`, `Qt.EditRole` and
                  `DTYPE_ROLE`.
  
          Returns:
              None if an invalid index is given, the role is not accepted by the
              model or the column is greater than `1`.
              The column name will be returned if the given column number equals `0`
              and the role is either `Qt.DisplayRole` or `Qt.EditRole`.
              The datatype will be returned, if the column number equals `1`. The
              `Qt.DisplayRole` or `Qt.EditRole` return a human readable, translated
              string, whereas the `DTYPE_ROLE` returns the raw data type.