+ void get_changes_as_properties (PBD::PropertyList& changes, Command* cmd) const {
+ if (!changed ()) {
+ return;
+ }
+
+ /* Create a property with just the changes and not the actual values */
+ SequenceProperty<Container>* a = create ();
+ a->_changes = _changes;
+ changes.add (a);
+
+ if (cmd) {
+ /* whenever one of the items emits DropReferences, make sure
+ that the Destructible we've been told to notify hears about
+ it. the Destructible is likely to be the Command being built
+ with this diff().
+ */
+
+ 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));
+ }
+ }
+ }
+
+ SequenceProperty<Container>* clone_from_xml (XMLNode const & node) const {
+
+ XMLNodeList const children = node.children ();
+
+ /* find the node for this property name */
+
+ std::string const c = capitalize (property_name ());
+ XMLNodeList::const_iterator i = children.begin();
+ while (i != children.end() && (*i)->name() != c) {
+ ++i;
+ }
+
+ if (i == children.end()) {
+ return 0;
+ }
+
+ /* create a property with the changes */
+
+ SequenceProperty<Container>* p = create ();
+
+ XMLNodeList const & grandchildren = (*i)->children ();
+ for (XMLNodeList::const_iterator j = grandchildren.begin(); j != grandchildren.end(); ++j) {
+
+ typename Container::value_type v = get_content_from_xml (**j);
+
+ if (!v) {
+ warning << "undo transaction references an unknown object" << endmsg;
+ } else if ((*j)->name() == "Add") {
+ p->_changes.added.insert (v);
+ } else if ((*j)->name() == "Remove") {
+ p->_changes.removed.insert (v);
+ }
+ }
+
+ return p;
+ }
+
+ /** Given an \<Add\> or \<Remove\> node as passed into get_content_to_xml, obtain an item */
+ virtual typename Container::value_type get_content_from_xml (XMLNode const & node) const = 0;
+
+ void clear_owned_changes () {
+ for (typename Container::iterator i = begin(); i != end(); ++i) {
+ (*i)->clear_changes ();
+ }
+ }
+
+ void rdiff (std::vector<Command*>& cmds) const {
+ for (typename Container::const_iterator i = begin(); i != end(); ++i) {
+ if ((*i)->changed ()) {
+ StatefulDiffCommand* sdc = new StatefulDiffCommand (*i);
+ cmds.push_back (sdc);
+ }
+ }
+ }
+
+ Container rlist() const { return _val; }
+