fix file-name reported to analyzer when stem-exporting
[ardour.git] / libs / pbd / stateful_diff_command.cc
index 1332cae4ff9720736f5611eed5bdcad209a60aba..5721b58fd0382d878c693d2903b551bd5f8beb41 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2010 Paul Davis 
+    Copyright (C) 2010 Paul Davis
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 */
 
 #include "pbd/stateful_diff_command.h"
-#include "i18n.h"
+#include "pbd/property_list.h"
+#include "pbd/demangle.h"
+#include "pbd/i18n.h"
 
 using namespace std;
 using namespace PBD;
 
 /** Create a new StatefulDiffCommand by examining the changes made to a Stateful
- *  since the last time that clear_history was called on it.
+ *  since the last time that clear_changes was called on it.
  *  @param s Stateful object.
  */
 
-StatefulDiffCommand::StatefulDiffCommand (Stateful* s)
-       : _object (s)
+StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<StatefulDestructible> s)
+        : _object (s)
+        , _changes (0)
 {
-       pair<XMLNode *, XMLNode*> const p = s->diff ();
-       _before = p.first;
-       _after = p.second;
+       _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.
+        */
+
+        s->DropReferences.connect_same_thread (*this, boost::bind (&Destructible::drop_references, this));
 }
 
-StatefulDiffCommand::StatefulDiffCommand (Stateful* s, XMLNode const & n)
+StatefulDiffCommand::StatefulDiffCommand (boost::shared_ptr<StatefulDestructible> s, XMLNode const & n)
        : _object (s)
+        , _changes (0)
 {
-       _before = new XMLNode (*n.children().front());
-       _after = new XMLNode (*n.children().back());
-}
+        const XMLNodeList& children (n.children());
+
+        for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
+                if ((*i)->name() == X_("Changes")) {
+                        _changes = s->property_factory (**i);
+                }
+       }
 
+        assert (_changes != 0);
+
+        /* if the stateful object that this command refers to goes away,
+           be sure to notify owners of this command.
+        */
+
+        s->DropReferences.connect_same_thread (*this, boost::bind (&Destructible::drop_references, this));
+}
 
 StatefulDiffCommand::~StatefulDiffCommand ()
 {
-       delete _before;
-       delete _after;
+        drop_references ();
+
+        delete _changes;
 }
 
 void
 StatefulDiffCommand::operator() ()
 {
-       _object->set_state (*_after, Stateful::current_state_version);
+       boost::shared_ptr<Stateful> s (_object.lock());
+
+       if (s) {
+                s->apply_changes (*_changes);
+       }
 }
 
 void
 StatefulDiffCommand::undo ()
 {
-       _object->set_state (*_before, Stateful::current_state_version);
+       boost::shared_ptr<Stateful> s (_object.lock());
+
+       if (s) {
+               PropertyList p = *_changes;
+               p.invert ();
+                s->apply_changes (p);
+       }
 }
 
 XMLNode&
 StatefulDiffCommand::get_state ()
 {
+       boost::shared_ptr<Stateful> s (_object.lock());
+
+       if (!s) {
+               /* XXX should we throw? */
+               return * new XMLNode("");
+       }
+
        XMLNode* node = new XMLNode (X_("StatefulDiffCommand"));
 
-       node->add_property ("obj-id", _object->id().to_s());
-       node->add_property ("type-name", typeid(*_object).name());
-       node->add_child_copy (*_before);
-       node->add_child_copy (*_after);
+       node->add_property ("obj-id", s->id().to_s());
+       node->add_property ("type-name", demangled_name (*s.get()));
+
+        XMLNode* changes = new XMLNode (X_("Changes"));
+
+        _changes->get_changes_as_xml (changes);
+
+        node->add_child_nocopy (*changes);
 
        return *node;
 }
+
+bool
+StatefulDiffCommand::empty () const
+{
+       return _changes->empty();
+}