title: QT: internal drag and drop of rows in QTableView, that changes order of rows in QTableModel
body: <p>I want to perform a sort of rows in QTableView, so that the underlying TableModel would have its data sorted, too:
  <img src="https://i.stack.imgur.com/qoie3.png" alt="enter image description here"></p>
  
  <p>If I'm not mistaken, built-in sorts in QTableView don't affect the order of rows in underlying TableModel, so I had to write a custom QTableView and custom QAbstractTableModel implementation of internal drag and drop.</p>
  
  <p>To test, if it works at all, I respond to any drag of cell by reordering first and second rows:</p>
  
  <pre><code>import sys
  from PyQt4.QtGui import *
  from PyQt4.QtCore import *
  
  class Model(QAbstractTableModel):
      def __init__(self):
          QAbstractTableModel.__init__(self, parent=None)
          self.data = [("elem1", "ACDC"), ("elem2", "GUNSNROSES"), ("elem3", "UFO")]
          self.setSupportedDragActions(Qt.MoveAction)
  
      def flags(self, index):
          if index.isValid():
              return Qt.ItemIsDragEnabled | Qt.ItemIsDropEnabled | Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable
          else:
              return Qt.ItemIsDropEnabled | Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable
  
      def rowCount(self, parent=QModelIndex()):
          return len(self.data)
  
      def columnCount(self, parent=QModelIndex()):
          return 1
  
      def data(self, index, role):
          if role == Qt.DisplayRole:
              print "row = %s" % int(index.row())
              return QVariant(self.data[int(index.row())][1])
          return QVariant()
  
      def headerData(self, index, orientation, role):
          if orientation == Qt.Horizontal and role == Qt.DisplayRole:
              return QVariant(str(index))
          elif orientation == Qt.Vertical and role == Qt.DisplayRole:
              return self.data[index][0]
  
      def dragMoveEvent(self, event):
          event.setDropAction(QtCore.Qt.MoveAction)
          event.accept()
  
      def moveRows(self, parent, source_first, source_last, parent2, dest):
          print "moveRows called, self.data = %s" % self.data
          self.beginMoveRows(parent, source_first, source_last, parent2, dest)
  
          self.data = self.data[1] + self.data[0] + self.data[2]
          self.endMoveRows()
          print "moveRows finished, self.data = %s" % self.data
  
  class View(QTableView):
      def __init__(self, parent=None):
          QTableView.__init__(self, parent=None)
          self.setSelectionMode(self.ExtendedSelection)
          self.setDragEnabled(True)
          self.acceptDrops()
          self.setDragDropMode(self.InternalMove)
          self.setDropIndicatorShown(True)
  
      def dragEnterEvent(self, event):
          event.accept()
  
      def dragMoveEvent(self, event):
          event.accept()
  
      def dropEvent(self, event):
          print "dropEvent called"
          point = event.pos()
          self.model().moveRows(QModelIndex(), 0, 0, QModelIndex(), 1)
          event.accept()
  
      def mousePressEvent(self, event):
          print "mousePressEvent called"
          self.startDrag(event)
  
      def startDrag(self, event):
          print "startDrag called"
          index = self.indexAt(event.pos())
          if not index.isValid():
              return
  
          self.moved_data = self.model().data[index.row()]
  
          drag = QDrag(self)
  
          mimeData = QMimeData()
          mimeData.setData("application/blabla", "")
          drag.setMimeData(mimeData)
  
          pixmap = QPixmap()
          pixmap = pixmap.grabWidget(self, self.visualRect(index))
          drag.setPixmap(pixmap)
  
          result = drag.start(Qt.MoveAction)
  
  class Application(object):
      def __init__(self):
          app = QApplication(sys.argv)
  
          self.window = QWidget()
          self.window.show()
  
          layout = QVBoxLayout(self.window)
  
          self.view = View()
          self.view.setModel(Model())
  
          layout.addWidget(self.view)
          sys.exit(app.exec_())
  </code></pre>
  
  <p>For some reason, this code doesn't work. It successfully starts the drag (well, almost successfully, cause it shows the previous row, instead of the current one as the drag icon), invokes <code>mousePressEvent</code>, <code>startDrag</code>, <code>dropEvent</code> and <code>moveRows</code> function, but then dies within <code>moveRows</code> with message:</p>
  
  <pre><code>Qt has caught an exception thrown from an event handler. Throwing
  exceptions from an event handler is not supported in Qt. You must
  reimplement QApplication::notify() and catch all exceptions there.
  
  Qt has caught an exception thrown from an event handler. Throwing
  exceptions from an event handler is not supported in Qt. You must
  reimplement QApplication::notify() and catch all exceptions there.
  
  terminate called after throwing an instance of 'std::bad_alloc'
    what():  std::bad_alloc
  Aborted
  </code></pre>
  
  <p>(Duplication of paragraph in error message is intentional - that's what it outputs verbatim).</p>
  
  <p>How do I debug this error? (inserting <code>try</code>-<code>except</code> in <code>moveRows</code> doesn't help)</p>
  
  <p>Do you have a better recipe for performing internal drag-and-drops, affecting the model in tableviews?</p>