title: How to remove row from QTreeView using QAbstractItemModel?
body: <p>I'm trying to just delete the QTreeView item "Node 6 (delete me)" from within the model.</p>
  
  <p>I can't get it to work, as nothing is deleted. What am I doing wrong?<br>
  See the <code>MainWindow.init</code> method for the removal code.</p>
  
  <p><a href="https://i.stack.imgur.com/ZcaBu.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ZcaBu.png" alt="enter image description here"></a></p>
  
  <pre><code>import sys
  
  try:
      from PySide2 import QtWidgets
  except ImportError:
      from PyQt5 import QtWidgets
  
  try:
      from PySide2 import QtCore
  except ImportError:
      from PyQt5 import QtCore
  
  
  class Node(object):
      def __init__(self, name, parent=None):
          self._name = name
          self._children = []
          self._parent = parent
  
          if parent is not None:
              parent.addChild(self)
  
      def addChild(self, child):
          self._children.append(child)
          child._parent = self
  
      def name(self):
          return self._name
  
      def child(self, row):
          return self._children[row]
  
      def insertChild(self, position, child):
          if position &lt; 0 or position &gt; len(self._children):
              return False
  
          self._children.insert(position, child)
          child._parent = self
          return True
  
      def childCount(self):
          return len(self._children)
  
      def parent(self):
          return self._parent
  
      def setParent(self, new_parent):
          self._parent._children.remove(self)
          self._parent = new_parent
          new_parent._children.append(self)
  
      def row(self):
          if self._parent is not None:
              return self._parent._children.index(self)
  
      def removeChild(self, position):
          if position &lt; 0 or position &gt; len(self._children):
              return False
          child = self._children.pop(position)
          child._parent = None
          return True
  
      def __repr__(self):
          return self._name
  
  
  class TreeModel(QtCore.QAbstractItemModel):
      def __init__(self, root, parent=None):
          super(TreeModel, self).__init__(parent)
          self._rootNode = root
  
      def rowCount(self, parent=QtCore.QModelIndex()):
          if not parent.isValid():
              parentNode = self._rootNode
          else:
              parentNode = parent.internalPointer()
  
          return parentNode.childCount()
  
      def columnCount(self, parent):
          return 1
  
      def data(self, index, role):
          """Return whatever the view should display"""
  
          if not index.isValid():
              return None
  
          node = index.internalPointer()
  
          if role == QtCore.Qt.DisplayRole:
              if index.column() == 0:
                  return node.name()
  
      def index(self, row, column, parent):
          if not parent.isValid():
              # parent is not valid when it is the root node, since the "parent"
              # method returns an empty QModelIndex
              parentNode = self._rootNode
          else:
              parentNode = parent.internalPointer()  # the node
  
          childItem = parentNode.child(row)
  
          return self.createIndex(row, column, childItem)
  
      def parent(self, index):
          node = index.internalPointer()
  
          parentNode = node.parent()
  
          if parentNode == self._rootNode:
              return QtCore.QModelIndex()
  
          return self.createIndex(parentNode.row(), 0, parentNode)
  
      def flags(self, index):
  
          # Original, inherited flags:
          original_flags = super(TreeModel, self).flags(index)
  
          return (original_flags | QtCore.Qt.ItemIsEnabled
                  | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDragEnabled
                  | QtCore.Qt.ItemIsDropEnabled)
  
      def headerData(self, section, orientation, role):
          if role == QtCore.Qt.DisplayRole:
              if section == 0:
                  return 'Node name'
  
  
  class MainWindow(QtWidgets.QMainWindow):
      def __init__(self):
          QtWidgets.QMainWindow.__init__(self)
  
          self.tree = QtWidgets.QTreeView()
          self.layout = QtWidgets.QGridLayout()
          self.main_widget = QtWidgets.QWidget()
  
          self.layout.addWidget(self.tree, 0, 0)
          self.main_widget.setLayout(self.layout)
          self.setCentralWidget(self.main_widget)
  
          # Note how these are added in a non-sorted fashion
          root_node = Node('Hidden root')
          Node(name='Node 3', parent=root_node)  # add using parent param
          n2 = Node(name='Node 2', parent=root_node)  # add using parent param
          Node(name='Node 1', parent=root_node)  # add using parent param
          n2.addChild(Node(name='Node 5'))  # add using addChild
          n2.addChild(Node(name='Node 6 (delete me)'))  # add using addChild
          n2.addChild(Node(name='Node 4'))  # add using addChild
  
          model = TreeModel(root=root_node)
          self.tree.setModel(model)
          self.tree.expandAll()
  
          # Attempt to remove a node from within the model
          node2 = model.index(1, 0, QtCore.QModelIndex())  # "Node 2" index
          index = model.index(1, 0, parent=node2)
          index_node = index.internalPointer()
          print('index represents node "%s" (its parent node is "%s")' %
              (index_node.name(), index.parent().internalPointer().name()))
          print('Removing %s on row %s' % (index_node.name(), index.row()))
          model.beginRemoveRows(index.parent(), index.row(), index.row())
          success = model.removeRow(index.row(), parent=index.parent())
          print('Removal was a succes?:', success)
          model.endRemoveRows()
  
  
  if __name__ == '__main__':
      app = QtWidgets.QApplication(sys.argv)
      main_window = MainWindow()
      main_window.show()
      sys.exit(app.exec_())
  </code></pre>