# HG changeset patch # User Thinker K.F. Li # Date 1295165617 -28800 # Node ID 6949e2b6cae2b629a8dafb41402853fa8839df4e # Parent 2a5da457474dbf015f2c03dde1f45ad5a157286b Add unlink clone checker. - Monitor changes of DOM-tree of the document - Unlinking a clone is actually removing the clone and copying nodes from the source. - Copy value of ID of a node to saved_id to track source of copy nodes. - For a new node with 'saved_id' is a copy of another node. - Copy vulae of 'saved_id' to 'ns0:duplicate-src' to keep the source - Change value of 'saved_id' to the value of ID of the node for later copying. - For a new node without 'saved_id' is not a copy of another node. - only set 'saved_id' to the value of its ID. diff -r 2a5da457474d -r 6949e2b6cae2 pyink/domview.py --- a/pyink/domview.py Sun Jan 16 11:04:29 2011 +0800 +++ b/pyink/domview.py Sun Jan 16 16:13:37 2011 +0800 @@ -484,6 +484,7 @@ gid = self.new_id() scene_group.setAttribute("id", gid) scene_group.setAttribute("inkscape:groupmode", "layer") + scene_group.setAttribute('scene_group', 'true') layer.group.appendChild(scene_group) diff -r 2a5da457474d -r 6949e2b6cae2 pyink/domview_ui.py --- a/pyink/domview_ui.py Sun Jan 16 11:04:29 2011 +0800 +++ b/pyink/domview_ui.py Sun Jan 16 16:13:37 2011 +0800 @@ -3,6 +3,7 @@ from frameline import frameline, frameruler from domview import domview import consistency +import unlink_clone ## \brief Maintain a stack of frameline UI component. # @@ -823,12 +824,14 @@ super(domview_ui_with_workers, self).__init__() self._consistency_checker = consistency.consistency_checker(self) + self._unlink_clone_checker = unlink_clone.unlink_clone_checker(self) pass def handle_doc_root(self, doc, root): super(domview_ui_with_workers, self).handle_doc_root(doc, root) self._consistency_checker.handle_doc_root(doc, root) + self._unlink_clone_checker.handle_doc_root(doc, root) pass pass diff -r 2a5da457474d -r 6949e2b6cae2 pyink/unlink_clone.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pyink/unlink_clone.py Sun Jan 16 16:13:37 2011 +0800 @@ -0,0 +1,109 @@ +import dom_event +from data_monitor import data_monitor + +class unlink_clone_checker(object): + __metaclass__ = data_monitor + + _no_change_attrs = ('ns0:duplicate-src', 'saved_id') + + def __init__(self, domview_ui): + self._domviewui = domview_ui + self._locker = domview_ui + self._doc = None + self._root = None + pass + + def _start_check(self): + doc = self._doc + dom_event.addEventListener(doc, 'DOMNodeInserted', + self.do_insert_node, None) + dom_event.addEventListener(doc, 'DOMAttrModified', + self.do_attr_modified, None) + pass + + def handle_doc_root(self, doc, root): + self._doc = doc + self._root = root + + self._start_check() + pass + + def _handle_unlinked_or_copied_nodes(self, node, child): + try: + saved_id = child.getAttribute('saved_id') + except: # Skip it for losting saved_id + pass + else: + child.setAttribute('ns0:duplicate-src', saved_id) + pass + + try: + child_id = child.getAttribute('id') + except: # still have no ID. + pass # Assign saved_id later with attr + # modified event. + else: + child.setAttribute('saved_id', child_id) + pass + pass + + def _handle_new_nodes(self, node, child): + if child.name() == 'svg:use': + return + + try: + child_id = child.getAttribute('id') + except KeyError: + return + child.setAttribute('saved_id', child_id) + pass + + ## \brief Check inserted node recurisvely. + # + # Travel the tree in post-order. + # + def _handle_insert_node_recursive(self, node, child): + # + # Traveling forest of children. + # + for cchild in child.childList(): + self._handle_insert_node_recursive(child, cchild) + pass + + # + # Visit the node + # + try: + child_id = child.getAttribute('saved_id') + except KeyError: # have no saved_id + pass + else: + self._handle_unlinked_or_copied_nodes(node, child) + return + + # have no saved_id + self._handle_new_nodes(node, child) + pass + + def do_insert_node(self, node, child): + self._handle_insert_node_recursive(node, child) + pass + + def do_attr_modified(self, node, name, old_value, new_value): + if name == 'id' and node.name() != 'svg:use': + # + # The ID of a node may not be assigned when it being + # inserted, and be assigned later. So, we checking + # attribute modification event to assign value of + # saved_id. + # + node.setAttribute('saved_id', new_value) + elif old_value and (name in self._no_change_attrs): + # + # Restore to old value for attributes that is not allowed + # to be changed by the user. + # + node.setAttribute(name, old_value) + pass + pass + pass