def setParent(self, itemId, newParentId):
        # Checks that the item is in the container
        if not self.containsId(itemId):
            return False

        # Gets the old parent
        oldParentId = self._parent.get(itemId)

        # Checks if no change is necessary
        if ((newParentId is None and oldParentId is None)
                or (newParentId is not None)
                and (newParentId == oldParentId)):
            return True

        # Making root?
        if newParentId is None:
            # The itemId should become a root so we need to
            # - Remove it from the old parent's children list
            # - Add it as a root
            # - Remove it from the item -> parent list (parent is null for
            # roots)

            # Removes from old parents children list
            l = self._children.get(oldParentId)
            if l is not None:
                l.remove(itemId)
                if len(l) == 0:
                    del self._children[oldParentId]

            # Add to be a root
            self._roots.append(itemId)

            # Updates parent
            del self._parent[itemId]

            if self.hasFilters():
                # Refilter the container if setParent is called when filters
                # are applied. Changing parent can change what is included in
                # the filtered version (if includeParentsWhenFiltering==true).
                self.doFilterContainer(self.hasFilters())

            self.fireItemSetChange()

            return True

        # We get here when the item should not become a root and we need to
        # - Verify the new parent exists and can have children
        # - Check that the new parent is not a child of the selected itemId
        # - Updated the item -> parent mapping to point to the new parent
        # - Remove the item from the roots list if it was a root
        # - Remove the item from the old parent's children list if it was not a
        # root

        # Checks that the new parent exists in container and can have
        # children
        if ((not self.containsId(newParentId))
                or (newParentId in self._noChildrenAllowed)):
            return False

        # Checks that setting parent doesn't result to a loop
        o = newParentId
        while (o is not None) and (o != itemId):
            o = self._parent.get(o)

        if o is not None:
            return False

        # Updates parent
        self._parent[itemId] = newParentId
        pcl = self._children.get(newParentId)
        if pcl is None:
            # Create an empty list for holding children if one were not
            # previously created
            pcl = list()
            self._children[newParentId] = pcl
        pcl.append(itemId)

        # Removes from old parent or root
        if oldParentId is None:
            self._roots.remove(itemId)
        else:
            l = self._children.get(oldParentId)
            if l is not None:
                l.remove(itemId)
                if len(l) == 0:
                    del self._children[oldParentId]

        if self.hasFilters():
            # Refilter the container if setParent is called when filters
            # are applied. Changing parent can change what is included in
            # the filtered version (if includeParentsWhenFiltering==true).
            self.doFilterContainer(self.hasFilters())

        self.fireItemSetChange()

        return True
Sets the parent of an Item. The new parent item must exist and be
dataset/ETHPy150Open rwl/muntjac/muntjac/data/util/hierarchical_container.py/HierarchicalContainer.setParent