title: How to re-arrange QTableView's Columns Order
body: <p>The code below creates a single QTableView driven by Model/Proxy framework.</p>
  
  <p>The <code>self.headerNames</code> list-variable declared in <code>source-model</code> stores the names of the Header's Columns. The number of names in this list is used by the same <code>source model</code>'s <code>columnCount()</code> method to return the number of column in a view:</p>
  
  <pre><code>def columnCount(self, parent=QModelIndex()):
      return len(self.headerNames)
  </code></pre>
  
  <p>The <code>Proxy</code> model's <code>headerData()</code> access this <code>self.headerNames</code> variable via <code>source model</code>:</p>
  
  <pre><code>sourceModel=self.sourceModel()
  </code></pre>
  
  <p>On <code>if role==Qt.DisplayRole</code> the Proxy retrieves and returns the name of the column to QTableView:</p>
  
  <pre><code>return QVariant( sourceModel.headerNames[column] )
  </code></pre>
  
  <p>There is a right-click menu implemented on header-column right-click.
  That portion is working fine. But since I could not find any examples on how others do it I had to design how it would work myself. I would appreciate if you find it could be improved.</p>
  
  <p>What I want to implement next is the ability to re-arrange the column in arbitrary order. But I am not sure where to start. </p>
  
  <p><img src="https://i.stack.imgur.com/9Nb7M.png" alt="enter image description here"></p>
  
  <p>P.s. Please disregard the names of the Items displayed in QTableView.
  I wanted to keep the code as simple as possible focusing on Header/Column subject only here.</p>
  
  <pre><code>from PyQt4.QtCore import *
  from PyQt4.QtGui import *
  import sys
  
  class Model(QAbstractTableModel):
      def __init__(self, parent=None, *args):
          QAbstractTableModel.__init__(self, parent, *args)
          self.items = ['Item_A_001','Item_A_002','Item_B_001','Item_B_002']
          self.headerNames=['Column 0','Column 1','Column 2','Column 3','Column 4','Column 5','Column 6','Column 7']
  
      def rowCount(self, parent=QModelIndex()):
          return len(self.items)       
      def columnCount(self, parent=QModelIndex()):
          return len(self.headerNames)
  
      def data(self, index, role):
          if not index.isValid(): return QVariant()
          elif role != Qt.DisplayRole:
              return QVariant()
  
          row=index.row()
          if row&lt;len(self.items):
              return QVariant(self.items[row])
          else:
              return QVariant()
  
  class Proxy(QSortFilterProxyModel):
      def __init__(self):
          super(Proxy, self).__init__()
  
      def filterAcceptsRow(self, row, parent):
          return True
  
      def headerData(self, column, orientation, role=Qt.DisplayRole):
          sourceModel=self.sourceModel()
  
          if role==Qt.TextAlignmentRole:
              if orientation==Qt.Horizontal:
                  return QVariant(int(Qt.AlignHCenter|Qt.AlignVCenter))
              return QVariant(int(Qt.AlignHCenter|Qt.AlignVCenter))
  
          if role==Qt.DisplayRole:
              if orientation==Qt.Horizontal:
                  return QVariant( sourceModel.headerNames[column] )
              else:
                  return QVariant()
          else:
              return QVariant()
  
          return QVariant(int(column+1))
  
  
  class MyWindow(QWidget):
      def __init__(self, *args):
          QWidget.__init__(self, *args)
  
          tableModel=Model(self)               
  
          proxyModel=Proxy()
          proxyModel.setSourceModel(tableModel)
  
          self.tableview=QTableView(self) 
          self.tableview.setModel(proxyModel)
          self.tableview.horizontalHeader().setStretchLastSection(True)
          self.tableview.setSelectionMode(QAbstractItemView.MultiSelection)
  
          header=self.tableview.horizontalHeader()
          header.setContextMenuPolicy(Qt.CustomContextMenu)
          header.connect(header, SIGNAL("customContextMenuRequested(QPoint)" ), self.headerRightClicked)
  
          self.resHeaderMenu=QMenu(self)
  
          for column in range(proxyModel.columnCount()):
              columnName=proxyModel.headerData(column, Qt.Horizontal).toPyObject()
              actn=QAction('%s'%columnName, self.resHeaderMenu, checkable=True)
              actn.setChecked(True)
              actn.triggered.connect(self.resHeaderMenuTriggered)
              self.resHeaderMenu.addAction(actn)
  
          layout = QVBoxLayout(self)
          layout.addWidget(self.tableview)
          self.setLayout(layout)
  
      def headerRightClicked(self, QPos):
          parentPosition=self.tableview.mapToGlobal(QPoint(0, 0))        
          menuPosition=parentPosition + QPos
          self.resHeaderMenu.move(menuPosition)
          self.resHeaderMenu.show()        
  
      def resHeaderMenuTriggered(self, arg):
          print 'resHeaderMenuTriggered', arg
          for i, actn in enumerate(self.resHeaderMenu.actions()):
              if not actn.isChecked():
                  self.tableview.setColumnHidden(i, True) 
  
  if __name__ == "__main__":
      app = QApplication(sys.argv)
      w = MyWindow()
      w.show()
      sys.exit(app.exec_())
  </code></pre>