comparison pyink/domview.py @ 1340:10d5f06f7566

Fix issue of shouting error when removing a node. - It shout a Python traceback message when removing a node that is referenced by a svg:use node. - when the node been removed, the node would be duplicated. The duplication was used to replace the svg:use one. - The ID of inserted duplication is the same as duplicated node, and modified to a new and unique ID. - Original design of domview_monitor can not handle it. - It is resolved by changing domview_monitor._id2node from single mapping to multiple mapping one.
author Thinker K.F. Li <thinker@codemud.net>
date Sun, 06 Feb 2011 23:12:48 +0800
parents 0b5ee9c90af7
children 972d749b9656
comparison
equal deleted inserted replaced
1339:20cf3e2a0a9d 1340:10d5f06f7566
626 self._on_remove_node, None) 626 self._on_remove_node, None)
627 dom_event.addEventListener(doc, 'DOMAttrModified', 627 dom_event.addEventListener(doc, 'DOMAttrModified',
628 self._on_attr_modified, None) 628 self._on_attr_modified, None)
629 pass 629 pass
630 630
631 ## \brief Add a node to id2node mapping.
632 #
633 # domview_monitor._id2node is a multiple mapping to map a key to
634 # multiple node. The reason that it is not a single mapping is
635 # Inkscape would insert a node with the ID from the node been
636 # copied, and change its ID to a unique one later. So, we must
637 # provide the capability to handle two or more nodes with the same
638 # ID.
639 def _map_id2node(self, node, node_id):
640 if node_id in self._id2node:
641 old_value = self._id2node[node_id]
642 if isinstance(old_value, list):
643 old_value.append(node)
644 else:
645 self._id2node[node_id] = [old_value, node]
646 pass
647 else:
648 self._id2node[node_id] = node
649 pass
650 pass
651
652 def _unmap_id2node(self, node, node_id):
653 if node_id not in self._id2node:
654 raise ValueError, 'invalide node ID (%s)' % (node_id)
655
656 value = self._id2node[node_id]
657 if isinstance(value, list):
658 value.remove(node)
659 if not value:
660 del self._id2node[node_id]
661 pass
662 pass
663 else:
664 del self._id2node[node_id]
665 pass
666 pass
667
631 ## \brief Rescan the tree. 668 ## \brief Rescan the tree.
632 # 669 #
633 def _monitor_reparse(self): 670 def _monitor_reparse(self):
634 self._maxframe = 0 671 self._maxframe = 0
635 self._id2node = {} 672 self._id2node = {}
647 try: 684 try:
648 child_id = child.getAttribute('id') 685 child_id = child.getAttribute('id')
649 except: 686 except:
650 pass 687 pass
651 else: 688 else:
652 if child_id not in self._id2node: 689 self._map_id2node(child, child_id)
653 self._id2node[child_id] = child
654 pass
655 pass 690 pass
656 691
657 if child.name() == 'ns0:scene' and _id_eq(node, self._scenes_node): 692 if child.name() == 'ns0:scene' and _id_eq(node, self._scenes_node):
658 try: 693 try:
659 ref = child.getAttribute('ref') 694 ref = child.getAttribute('ref')
705 try: 740 try:
706 child_id = child.getAttribute('id') 741 child_id = child.getAttribute('id')
707 except: 742 except:
708 pass 743 pass
709 else: 744 else:
710 if child_id not in self._id2node: 745 self._unmap_id2node(child, child_id)
711 raise ValueError, \
712 'remove a node that is never known (%s)' % (child_id)
713 del self._id2node[child_id]
714 pass 746 pass
715 747
716 if child.name() == 'ns0:scene' and _id_eq(node, self._scenes_node): 748 if child.name() == 'ns0:scene' and _id_eq(node, self._scenes_node):
717 try: 749 try:
718 ref = child.getAttribute('ref') 750 ref = child.getAttribute('ref')
735 def _on_attr_modified(self, node, name, old_value, new_value): 767 def _on_attr_modified(self, node, name, old_value, new_value):
736 if old_value == new_value: 768 if old_value == new_value:
737 return 769 return
738 770
739 if name == 'id': 771 if name == 'id':
740 if old_value and (old_value not in self._id2node): 772 if old_value and old_value in self._id2node:
741 raise ValueError, \ 773 self._unmap_id2node(node, old_value)
742 'old ID value of passed node is invalid one (%s)' % \
743 (old_value)
744 if (new_value in self._id2node):
745 raise ValueError, \
746 'new ID value of passed node is invalid one (%s)' % \
747 (new_value)
748
749 if old_value:
750 del self._id2node[old_value]
751 pass 774 pass
752 if new_value: 775 if new_value:
753 self._id2node[new_value] = node 776 self._map_id2node(node, new_value)
754 pass 777 pass
755 pass 778 pass
756 elif name == 'ref' and node.name() == 'ns0:scene': 779 elif name == 'ref' and node.name() == 'ns0:scene':
757 parent_node = node.parent() 780 parent_node = node.parent()
758 scenes_node = self._scenes_node 781 scenes_node = self._scenes_node
870 pass 893 pass
871 894
872 ## \brief Return the node with given ID. 895 ## \brief Return the node with given ID.
873 # 896 #
874 def get_node(self, node_id): 897 def get_node(self, node_id):
875 return self._id2node[node_id] 898 value = self._id2node[node_id]
899 if isinstance(value, list):
900 return value[-1]
901 return value
876 902
877 ## \brief Return a scene node corresponding to a scene group of given ID. 903 ## \brief Return a scene node corresponding to a scene group of given ID.
878 # 904 #
879 def get_scene(self, group_id): 905 def get_scene(self, group_id):
880 return self._group2scene[group_id] 906 return self._group2scene[group_id]