Modify StatefulDiffCommand undo record to only contain the changes in one direction...
authorCarl Hetherington <carl@carlh.net>
Wed, 25 Aug 2010 17:31:57 +0000 (17:31 +0000)
committerCarl Hetherington <carl@carlh.net>
Wed, 25 Aug 2010 17:31:57 +0000 (17:31 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@7684 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/playlist.h
libs/ardour/playlist.cc
libs/pbd/pbd/properties.h
libs/pbd/pbd/property_basics.h
libs/pbd/pbd/property_list.h
libs/pbd/pbd/sequence_property.h
libs/pbd/pbd/stateful.h
libs/pbd/pbd/stateful_diff_command.h
libs/pbd/property_list.cc
libs/pbd/stateful.cc
libs/pbd/stateful_diff_command.cc

index b60fa62879da9d4c7a94537d47548dc0bd7b4505..50ddd224695e616cc85c26140ffa059ff39b3b10 100644 (file)
@@ -63,10 +63,12 @@ class RegionListProperty : public PBD::SequenceProperty<std::list<boost::shared_
   public:
         RegionListProperty (Playlist&);
 
+       RegionListProperty* clone () const;
+
         boost::shared_ptr<Region> lookup_id (const PBD::ID& id);
 
   private:
-       PBD::SequenceProperty<std::list<boost::shared_ptr<Region> > >* create () const;
+       RegionListProperty* create () const;
 
         friend class Playlist;
         /* we live and die with our playlist, no lifetime management needed */
index 2062f343d955a25d14422a18660eb41fec687525..e6b8abf21a61a4dcbce29655e0cb5d67fae4ecae 100644 (file)
@@ -124,7 +124,12 @@ RegionListProperty::lookup_id (const ID& id)
         return ret;
 }
 
-SequenceProperty<std::list<boost::shared_ptr<Region> > >* RegionListProperty::create () const
+RegionListProperty* RegionListProperty::clone () const
+{
+       return new RegionListProperty (*this);
+}
+
+RegionListProperty* RegionListProperty::create () const
 {
        return new RegionListProperty (_playlist);
 }
index 13790973e239950b4d82d45b78debc97551047cd..41a5f748810ffe79b26873b81a91a239a14e8ef4 100644 (file)
@@ -24,7 +24,7 @@
 #include <sstream>
 #include <list>
 #include <set>
-#include <glib.h>
+#include <iostream>
 
 #include "pbd/xml++.h"
 #include "pbd/property_basics.h"
@@ -45,6 +45,13 @@ public:
                , _current (v)
        {}
 
+       PropertyTemplate (PropertyDescriptor<T> p, T const& o, T const& c)
+               : PropertyBase (p.property_id)
+               , _have_old (true)
+               , _current (c)
+               , _old (o)
+       {}
+       
        PropertyTemplate<T>& operator=(PropertyTemplate<T> const& s) {
                /* XXX: isn't there a nicer place to do this? */
                _have_old    = s._have_old;
@@ -85,11 +92,10 @@ public:
                _have_old = false;
        }
 
-       void get_change (XMLNode* history_node) const {
-               /* We can get to the current state of a scalar property like this one simply
-                  by knowing what the new state is.
-               */
-                history_node->add_property (property_name(), to_string (_current));
+       void get_changes_as_xml (XMLNode* history_node) const {
+               XMLNode* node = history_node->add_child (property_name());
+                node->add_property ("from", to_string (_old));
+                node->add_property ("to", to_string (_current));
        }
 
        bool set_value (XMLNode const & node) {
@@ -114,13 +120,21 @@ public:
 
        bool changed () const { return _have_old; }
        
-       void apply_change (PropertyBase const * p) {
+       void apply_changes (PropertyBase const * p) {
                T v = dynamic_cast<const PropertyTemplate<T>* > (p)->val ();
+               std::cout << "Apply changes: " << v << " cf " << _current << "\n";
                if (v != _current) {
                        set (v);
                }
        }
 
+       void invert () {
+               T const tmp = _current;
+               _current = _old;
+               _old = tmp;
+               std::cout << "Inverted to " << _old << " -> " << _current << "\n";
+       }
+
 protected:
         /** Constructs a PropertyTemplate with a default
             value for _old and _current.
@@ -175,20 +189,39 @@ public:
        Property (PropertyDescriptor<T> q, T const& v)
                : PropertyTemplate<T> (q, v)
        {}
-        
-        void diff (PropertyList& undo, PropertyList& redo, Command* /*ignored*/) const {
+
+       Property (PropertyDescriptor<T> q, T const& o, T const& c)
+               : PropertyTemplate<T> (q, o, c)
+       {}
+
+       Property<T>* clone () const {
+               return new Property<T> (*this);
+       }
+       
+        void get_changes_as_properties (PropertyList& changes, Command *) const {
                 if (this->_have_old) {
-                        undo.add (new Property<T> (this->property_id(), this->_old));
-                        redo.add (new Property<T> (this->property_id(), this->_current));
+                       changes.add (new Property<T> (*this));
                 }
         }
 
         Property<T>* maybe_clone_self_if_found_in_history_node (const XMLNode& node) const {
-                const XMLProperty* prop = node.property (this->property_name());
-                if (!prop) {
-                        return 0;
-                }
-                return new Property<T> (this->property_id(), from_string (prop->value()));
+               XMLNodeList const & children = node.children ();
+               XMLNodeList::const_iterator i = children.begin();
+               while (i != children.end() && (*i)->name() != this->property_name()) {
+                       ++i;
+               }
+
+               if (i == children.end()) {
+                       return 0;
+               }
+               XMLProperty* from = (*i)->property ("from");
+               XMLProperty* to = (*i)->property ("to");
+                               
+               if (!from || !to) {
+                       return 0;
+               }
+                       
+               return new Property<T> (this->property_id(), from_string (from->value()), from_string (to->value ()));
         }
 
        T & operator=(T const& v) {
@@ -238,11 +271,14 @@ public:
                : PropertyTemplate<std::string> (q, v)
        {}
 
-        void diff (PropertyList& before, PropertyList& after, Command* /*ignored*/) const {
+       Property<std::string>* clone () const {
+               return new Property<std::string> (*this);
+       }
+       
+        void get_changes_as_properties (PropertyList& changes, Command* /*ignored*/) const {
                 if (this->_have_old) {
-                        before.add (new Property<std::string> (PropertyDescriptor<std::string> (this->property_id()), this->_old));
-                        after.add (new Property<std::string> (PropertyDescriptor<std::string> (this->property_id()), this->_current));
-                }
+                       changes.add (new Property<std::string> (*this));
+               }
         }
 
        std::string & operator=(std::string const& v) {
index 433a25a59b7398573632505e4ff37ab4c048e361..f32991628461bfe851effdd7387e0f2c55bf9fc7 100644 (file)
@@ -87,6 +87,8 @@ public:
        {}
 
        virtual ~PropertyBase () {}
+
+       virtual PropertyBase* clone () const = 0;
         
        /** Forget about any old value for this state */
        virtual void clear_history () = 0;
@@ -94,15 +96,10 @@ public:
        /** Tell any things we own to forget about their old values */
        virtual void clear_owned_history () {}
 
-        /** Get any change in this property as XML and add it to a node */
-       virtual void get_change (XMLNode *) const = 0;
-
-       /** Add information to two property lists: one that allows
-        *  undo of the changes in this property's state betwen now and
-        *  the last call to clear_history, and one that allows redo
-        *  of those changes.
-        */
-       virtual void diff (PropertyList& undo, PropertyList& redo, Command*) const = 0;
+        /** Get any changes in this property as XML and add it to a node */
+       virtual void get_changes_as_xml (XMLNode *) const = 0;
+       
+       virtual void get_changes_as_properties (PropertyList& changes, Command *) const = 0;
 
        /** Collect StatefulDiffCommands for changes to anything that we own */
        virtual void rdiff (std::vector<StatefulDiffCommand*> &) const {}
@@ -122,8 +119,11 @@ public:
         */
        virtual bool changed() const = 0;
 
-       /** Apply a change contained in another Property to this one */
-       virtual void apply_change (PropertyBase const *) = 0;
+       /** Apply changes contained in another Property to this one */
+       virtual void apply_changes (PropertyBase const *) = 0;
+
+       /** Invert the changes in this property */
+       virtual void invert () = 0;
 
        const gchar*property_name () const { return g_quark_to_string (_property_id); }
        PropertyID  property_id () const   { return _property_id; }
index 04112bad80001f26274349bf4ce1c98f30bf1699..12b7995009c7fe2ecac307f57b57438a6a803327 100644 (file)
@@ -32,11 +32,13 @@ namespace PBD {
 class PropertyList : public std::map<PropertyID, PropertyBase*>
 {
 public:
-       PropertyList();
+       PropertyList ();
+       PropertyList (PropertyList const &);
         
        virtual ~PropertyList();
 
-        void get_changes (XMLNode *);
+        void get_changes_as_xml (XMLNode *);
+       void invert ();
 
         /** Add a property (of some kind) to the list. Used when
             constructing PropertyLists that describe a change/operation.
index 00774104216974126ff48e85ebbf1372864b2789..573bb4b539c8471c5932400ceeff74fc0636efa5 100644 (file)
@@ -79,37 +79,29 @@ class SequenceProperty : public PropertyBase
 
        SequenceProperty (PropertyID id, const boost::function<void(const ChangeRecord&)>& update)
                 : PropertyBase (id), _update_callback (update) {}
-        
-       virtual typename Container::value_type lookup_id (const PBD::ID&) = 0;
-
-        void invert_changes () {
 
-                /* reverse the adds/removes so that this property's change member
-                   correctly describes how to undo the changes it currently
-                   reflects. A derived instance of this type of property will
-                   create a diff() pair by copying the property twice, and
-                   calling this method on the "before" item of the pair.
-                */
+       virtual typename Container::value_type lookup_id (const PBD::ID&) = 0;
 
-               _change.removed.swap (_change.added);
+        void invert () {
+               _changes.removed.swap (_changes.added);
         }
 
-       void get_change (XMLNode* history_node) const {
+       void get_changes_as_xml (XMLNode* history_node) const {
 
                 XMLNode* child = new XMLNode (PBD::capitalize (property_name()));
                 history_node->add_child_nocopy (*child);
                 
                /* record the change described in our change member */
 
-               if (!_change.added.empty()) {
-                       for (typename ChangeContainer::iterator i = _change.added.begin(); i != _change.added.end(); ++i) {
+               if (!_changes.added.empty()) {
+                       for (typename ChangeContainer::iterator i = _changes.added.begin(); i != _changes.added.end(); ++i) {
                                 XMLNode* add_node = new XMLNode ("Add");
                                 child->add_child_nocopy (*add_node);
                                 add_node->add_property ("id", (*i)->id().to_s());
                        }
                }
-               if (!_change.removed.empty()) {
-                       for (typename ChangeContainer::iterator i = _change.removed.begin(); i != _change.removed.end(); ++i) {
+               if (!_changes.removed.empty()) {
+                       for (typename ChangeContainer::iterator i = _changes.removed.begin(); i != _changes.removed.end(); ++i) {
                                 XMLNode* remove_node = new XMLNode ("Remove");
                                 child->add_child_nocopy (*remove_node);
                                 remove_node->add_property ("id", (*i)->id().to_s());
@@ -130,16 +122,16 @@ class SequenceProperty : public PropertyBase
        }
 
        bool changed () const {
-               return !_change.added.empty() || !_change.removed.empty();
+               return !_changes.added.empty() || !_changes.removed.empty();
        }
        
        void clear_history () {
-               _change.added.clear ();
-               _change.removed.clear ();
+               _changes.added.clear ();
+               _changes.removed.clear ();
        }
 
-       void apply_change (PropertyBase const * p) {
-               const ChangeRecord& change (dynamic_cast<const SequenceProperty*> (p)->change ());
+       void apply_changes (PropertyBase const * p) {
+               const ChangeRecord& change (dynamic_cast<const SequenceProperty*> (p)->changes ());
                update (change);
        }
 
@@ -154,14 +146,10 @@ class SequenceProperty : public PropertyBase
                _update_callback (cr);
        }
 
-       void diff (PBD::PropertyList& undo, PBD::PropertyList& redo, Command* cmd) const {
+       void get_changes_as_properties (PBD::PropertyList& changes, Command* cmd) const {
                if (changed ()) {
-                       /* list of the removed/added items since clear_history() was last called */
                        SequenceProperty<Container>* a = copy_for_history ();
-
-                       /* the same list, but with removed/added lists swapped (for undo purposes) */
-                       SequenceProperty<Container>* b = copy_for_history ();
-                       b->invert_changes ();
+                       changes.add (a);
 
                        if (cmd) {
                                /* whenever one of the items emits DropReferences, make sure
@@ -170,13 +158,10 @@ class SequenceProperty : public PropertyBase
                                   with this diff().
                                */
                         
-                               for (typename ChangeContainer::iterator i = a->change().added.begin(); i != a->change().added.end(); ++i) {
+                               for (typename ChangeContainer::iterator i = a->changes().added.begin(); i != a->changes().added.end(); ++i) {
                                        (*i)->DropReferences.connect_same_thread (*cmd, boost::bind (&Destructible::drop_references, cmd));
                                }
                         }
-                       
-                       undo.add (b);
-                       redo.add (a);
                }
         }
 
@@ -190,7 +175,7 @@ class SequenceProperty : public PropertyBase
                                
                                SequenceProperty<Container>* p = create ();
                                
-                               if (p->set_change (**i)) {
+                               if (p->set_changes (**i)) {
                                        return p;
                                } else {
                                        delete p;
@@ -232,51 +217,51 @@ class SequenceProperty : public PropertyBase
        typename Container::const_reverse_iterator rend() const { return _val.rend(); }
 
        typename Container::iterator insert (typename Container::iterator i, const typename Container::value_type& v) {
-               _change.add (v);
+               _changes.add (v);
                return _val.insert (i, v);
        }
 
        typename Container::iterator erase (typename Container::iterator i) {
                if (i != _val.end()) {
-                       _change.remove (*i);
+                       _changes.remove (*i);
                }
                return _val.erase (i);
        }
 
        typename Container::iterator erase (typename Container::iterator f, typename Container::iterator l) {
                for (typename Container::const_iterator i = f; i != l; ++i) {
-                       _change.remove (*i);
+                       _changes.remove (*i);
                }
                return _val.erase (f, l);
        }
 
        void push_back (const typename Container::value_type& v) {
-               _change.add (v);
+               _changes.add (v);
                _val.push_back (v);
        }
 
        void push_front (const typename Container::value_type& v) {
-               _change.add (v);
+               _changes.add (v);
                _val.push_front (v);
        }
 
        void pop_front () {
                 if (!_val.empty()) {
-                        _change.remove (front());
+                        _changes.remove (front());
                 }
                _val.pop_front ();
        }
 
        void pop_back () {
                 if (!_val.empty()) {
-                        _change.remove (back());
+                        _changes.remove (back());
                 }
                _val.pop_back ();
        }
 
        void clear () {
                for (typename Container::iterator i = _val.begin(); i != _val.end(); ++i) {
-                       _change.remove (*i);
+                       _changes.remove (*i);
                }
                _val.clear ();
        }
@@ -291,10 +276,10 @@ class SequenceProperty : public PropertyBase
 
        Container& operator= (const Container& other) {
                for (typename Container::iterator i = _val.begin(); i != _val.end(); ++i) {
-                       _change.remove (*i);
+                       _changes.remove (*i);
                }
                for (typename Container::iterator i = other.begin(); i != other.end(); ++i) {
-                       _change.add (*i);
+                       _changes.add (*i);
                }
                return _val = other;
        }
@@ -323,18 +308,18 @@ class SequenceProperty : public PropertyBase
                _val.sort (comp);
        }
         
-        const ChangeRecord& change() const { return _change; }
+        const ChangeRecord& changes () const { return _changes; }
 
   protected:
        Container _val;
-       ChangeRecord _change;
+       ChangeRecord _changes;
        boost::function<void(const ChangeRecord&)> _update_callback;
 
         /** Load serialized change history.
          * @return true if loading succeeded, false otherwise
          */
 
-       bool set_change (XMLNode const & history_node) {
+       bool set_changes (XMLNode const & history_node) {
 
                 const XMLNodeList& children (history_node.children());
 
@@ -348,9 +333,9 @@ class SequenceProperty : public PropertyBase
                                         return false;
                                 }
                                 if ((*i)->name() == "Add") {
-                                        _change.added.insert (v);
+                                        _changes.added.insert (v);
                                 } else if ((*i)->name() == "Remove") {
-                                        _change.removed.insert (v);
+                                        _changes.removed.insert (v);
                                 }
                         }
                 }
@@ -370,7 +355,7 @@ private:
        SequenceProperty<Container>* copy_for_history () const {
                SequenceProperty<Container>* copy = create ();
                /* this is all we need */
-               copy->_change = _change;
+               copy->_changes = _changes;
                return copy;
        }
 };
index af26caab07855a8eee72d50f1ac9820ebae56126..050540dcd14b1d82889cd30e5c53740d1b591120 100644 (file)
@@ -49,7 +49,7 @@ class Stateful {
        virtual XMLNode& get_state (void) = 0;
        virtual int set_state (const XMLNode&, int version) = 0;
 
-       virtual bool apply_change (PropertyBase const &);
+       virtual bool apply_changes (PropertyBase const &);
        PropertyChange apply_changes (PropertyList const &);
        
         const OwnedPropertyList& properties() const { return *_properties; }
@@ -69,7 +69,7 @@ class Stateful {
 
        void clear_history ();
        virtual void clear_owned_history ();
-        void diff (PropertyList&, PropertyList&, Command*) const;
+        PropertyList* get_changes_as_properties (Command *) const;
        virtual void rdiff (std::vector<StatefulDiffCommand*> &) const;
         bool changed() const;
 
index 25cdfbba12c24f12a92bed4f6884b15d3735eed9..2d5c234d762f7d58963ef888a473e2614afa1d22 100644 (file)
@@ -47,8 +47,7 @@ public:
 
 private:
        boost::weak_ptr<Stateful> _object; ///< the object in question
-        PBD::PropertyList* _undo; ///< its (partial) state before the command, to allow undo
-        PBD::PropertyList* _redo;  ///< its (partial) state after the operation, to allow redo
+        PBD::PropertyList* _changes; ///< property changes to execute this command
 };
 
 };
index 5c0de4bacfc776254cb7458398d01cdf9d8706de..efae95e45e4e17e7ad16510832b6cabd1a83ee03 100644 (file)
@@ -27,6 +27,20 @@ using namespace PBD;
 PropertyList::PropertyList() 
         : _property_owner (true) 
 {
+       
+}
+
+PropertyList::PropertyList (PropertyList const & other)
+       : std::map<PropertyID, PropertyBase*> (other)
+       , _property_owner (other._property_owner)
+{
+       if (_property_owner) {
+               /* make our own copies of the properties */
+               clear ();
+               for (std::map<PropertyID, PropertyBase*>::const_iterator i = other.begin(); i != other.end(); ++i) {
+                       insert (std::make_pair (i->first, i->second->clone ()));
+               }
+       }
 }
 
 PropertyList::~PropertyList ()
@@ -39,13 +53,13 @@ PropertyList::~PropertyList ()
 }
 
 void
-PropertyList::get_changes (XMLNode* history_node)
+PropertyList::get_changes_as_xml (XMLNode* history_node)
 {
         for (const_iterator i = begin(); i != end(); ++i) {
-                DEBUG_TRACE (DEBUG::Properties, string_compose ("Add before/after to %1 for %2\n",
+                DEBUG_TRACE (DEBUG::Properties, string_compose ("Add changes to %1 for %2\n",
                                                                 history_node->name(), 
                                                                 i->second->property_name()));
-                i->second->get_change (history_node);
+                i->second->get_changes_as_xml (history_node);
         }
 }
 
@@ -53,7 +67,15 @@ bool
 PropertyList::add (PropertyBase* prop)
 {
         return insert (value_type (prop->property_id(), prop)).second;
-}        
+}
+
+void
+PropertyList::invert ()
+{
+       for (iterator i = begin(); i != end(); ++i) {
+               i->second->invert ();
+       }
+}
 
 OwnedPropertyList::OwnedPropertyList ()
 {
index 6ea8f19128d789b9ca1c1121d14c18189af2a5e9..204e62685e49eeec8dd7533a5a9ba2931261a5b6 100644 (file)
@@ -166,12 +166,16 @@ Stateful::clear_history ()
        }
 }
 
-void
-Stateful::diff (PropertyList& before, PropertyList& after, Command* cmd) const
+PropertyList *
+Stateful::get_changes_as_properties (Command* cmd) const
 {
+       PropertyList* pl = new PropertyList;
+       
        for (OwnedPropertyList::const_iterator i = _properties->begin(); i != _properties->end(); ++i) {
-               i->second->diff (before, after, cmd);
+               i->second->get_changes_as_properties (*pl, cmd);
        }
+
+       return pl;
 }
 
 /** Set our property values from an XML node.
@@ -209,8 +213,13 @@ Stateful::apply_changes (const PropertyList& property_list)
         
         for (PropertyList::const_iterator i = property_list.begin(); i != property_list.end(); ++i) {
                 if ((p = _properties->find (i->first)) != _properties->end()) {
-                        DEBUG_TRACE (DEBUG::Stateful, string_compose ("actually setting property %1\n", p->second->property_name()));
-                       if (apply_change (*i->second)) {
+
+                        DEBUG_TRACE (
+                               DEBUG::Stateful,
+                               string_compose ("actually setting property %1 using %2\n", p->second->property_name(), i->second->property_name())
+                               );
+                       
+                       if (apply_changes (*i->second)) {
                                c.add (i->first);
                        }
                } else {
@@ -303,14 +312,14 @@ Stateful::changed() const
 }
 
 bool
-Stateful::apply_change (const PropertyBase& prop)
+Stateful::apply_changes (const PropertyBase& prop)
 {
        OwnedPropertyList::iterator i = _properties->find (prop.property_id());
        if (i == _properties->end()) {
                return false;
        }
 
-       i->second->apply_change (&prop);
+       i->second->apply_changes (&prop);
        return true;
 }
 
index 857235b803dd612b464b1529ac11c0e153be7dbd..ffd56c8fb1866d62b7f0b6d82185158e0cde926c 100644 (file)
@@ -34,10 +34,9 @@ using namespace PBD;
 
 StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<StatefulDestructible> s)
         : _object (s)
-        , _undo (new PropertyList)
-        , _redo (new PropertyList)
+        , _changes (0)
 {
-        s->diff (*_undo, *_redo, this);
+       _changes = s->get_changes_as_properties (this);
 
         /* if the stateful object that this command refers to goes away,
            be sure to notify owners of this command.
@@ -48,21 +47,17 @@ StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<StatefulDestructible
 
 StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<StatefulDestructible> s, XMLNode const & n)
        : _object (s)
-        , _undo (0)
-        , _redo (0)
+        , _changes (0)
 {
         const XMLNodeList& children (n.children());
 
         for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
-                if ((*i)->name() == X_("Undo")) {
-                        _undo = s->property_factory (**i);
-                } else if ((*i)->name() == X_("Do")) {
-                        _redo = s->property_factory (**i);
+                if ((*i)->name() == X_("Changes")) {
+                        _changes = s->property_factory (**i);
                 }
-        }
+       }
 
-        assert (_undo != 0);
-        assert (_redo != 0);
+        assert (_changes != 0);
 
         /* if the stateful object that this command refers to goes away,
            be sure to notify owners of this command.
@@ -75,8 +70,7 @@ StatefulDiffCommand::~StatefulDiffCommand ()
 {
         drop_references ();
 
-        delete _undo;
-        delete _redo;
+        delete _changes;
 }
 
 void
@@ -85,7 +79,7 @@ StatefulDiffCommand::operator() ()
        boost::shared_ptr<Stateful> s (_object.lock());
 
        if (s) {
-                s->apply_changes (*_redo);
+                s->apply_changes (*_changes);
        }
 }
 
@@ -95,8 +89,9 @@ StatefulDiffCommand::undo ()
        boost::shared_ptr<Stateful> s (_object.lock());
 
        if (s) {
-                std::cerr << "Undoing a stateful diff command\n";
-                s->apply_changes (*_undo);
+               PropertyList p = *_changes;
+               p.invert ();
+                s->apply_changes (p);
        }
 }
 
@@ -115,14 +110,11 @@ StatefulDiffCommand::get_state ()
        node->add_property ("obj-id", s->id().to_s());
        node->add_property ("type-name", demangled_name (*s.get()));
 
-        XMLNode* undo = new XMLNode (X_("Undo"));
-        XMLNode* redo = new XMLNode (X_("Do"));
+        XMLNode* changes = new XMLNode (X_("Changes"));
 
-        _undo->get_changes (undo);
-        _redo->get_changes (redo);
+        _changes->get_changes_as_xml (changes);
         
-        node->add_child_nocopy (*undo);
-        node->add_child_nocopy (*redo);
+        node->add_child_nocopy (*changes);
 
        return *node;
 }