Python – QTableView: Sorted by heading index -1

QTableView: Sorted by heading index -1… here is a solution to the problem.

QTableView: Sorted by heading index -1

I’m using PyQt4 and have a QTableView with 2 columns of data.
The index has an extra column (which comes from the headerData function of the source model). To sort when the title button is clicked, I wrapped my model with a proxy class.

Works fine, but I also want to sort by the first column by clicking the top left button (I'd say column number: -1:

).

http://res.cloudinary.com/dfrkaf37y/image/upload/v1671597271/etbye/ABkcJ.png

On request, this is a minimal example:

from PyQt4 import QtCore, QtGui
import random, sys

class MyModel(QtCore.QAbstractTableModel):

headers = 'Name', 'Value'

def __init__(self, parent=None):
    super(MyModel, self).__init__(parent)

# Dummy data
    rows = []
    columns = []    
    for i in range(10):
      numbr = random.randint(1,20)
      rows.append('Name #%i' % numbr)
      columns.append('Value #%i' % numbr)
    self.data = zip(rows, columns)

def columnCount(self, parent=QtCore.QModelIndex()):
    return 2

def rowCount(self, parent=QtCore.QModelIndex()): 
    return len(self.data)

def data(self, index, role=QtCore.Qt.DisplayRole):
    if not index.isValid():
      return None

if (index.row() >= len(self.data)) or (index.row() < 0):
      return None

if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
      return self.data[index.row()][index.column()]

return None

def headerData(self, section, orientation, role):
    if role == QtCore.Qt.DisplayRole :
        if orientation == QtCore.Qt.Horizontal :
            return self.headers[section]
        elif orientation == QtCore.Qt.Vertical :
            return section
    return None

class MyProxyModel(QtGui.QSortFilterProxyModel):
    def __init__(self):
      super(MyProxyModel, self).__init__()

def lessThan(self, left_index, right_index):
      left_var = left_index.data(QtCore.Qt.EditRole)
      right_var = right_index.data(QtCore.Qt.EditRole)

# Column #1 (values) should be not sortable
      if left_index.column() == 1: 
        return False

return left_var < right_var

class MainWindow(QtGui.QMainWindow):
  def __init__(self):
    super(MainWindow, self).__init__()     

self.model = MyModel()

self.proxy = MyProxyModel()
    self.proxy.setSourceModel(self.model)
    self.proxy.setFilterKeyColumn(0)

self.selectionModel = QtGui.QItemSelectionModel(self.proxy)

self.tableView = QtGui.QTableView()
    self.tableView.setModel(self.proxy)    
    self.tableView.setSelectionModel(self.selectionModel)

self.tableView.setSortingEnabled(True)
    self.tableView.sortByColumn(0, QtCore.Qt.AscendingOrder)    
    self.setCentralWidget(self.tableView) 

if __name__ == '__main__':
  app = QtGui.QApplication(sys.argv)
  window = MainWindow()
  window.show()
  sys.exit(app.exec_())

Can someone help me?

Solution

First of all, you have to be able to get cornerWidget, which is a QAbstractButton, and for that we use findChild. Then we use sort(-1) to invalidate the sort and put it into the initial state.

class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        ...    
        self.setCentralWidget(self.tableView) 
        cornerButton = self.tableView.findChild(QtGui.QAbstractButton)
        cornerButton.clicked.connect(lambda: self.proxy.sort(-1))

Related Problems and Solutions