#include <unistd.h>
-#include <pbd/stateful.h>
-#include <pbd/filesystem.h>
-#include <pbd/xml++.h>
-#include <pbd/error.h>
+#include "pbd/debug.h"
+#include "pbd/stateful.h"
+#include "pbd/property_list.h"
+#include "pbd/properties.h"
+#include "pbd/destructible.h"
+#include "pbd/filesystem.h"
+#include "pbd/xml++.h"
+#include "pbd/error.h"
#include "i18n.h"
+using namespace std;
+
namespace PBD {
+int Stateful::current_state_version = 0;
+int Stateful::loading_state_version = 0;
+
Stateful::Stateful ()
+ : _frozen (0)
+ , _properties (new OwnedPropertyList)
{
_extra_xml = 0;
_instant_xml = 0;
Stateful::~Stateful ()
{
+ delete _properties;
+
// Do not delete _extra_xml. The use of add_child_nocopy()
// means it needs to live on indefinately.
- if (_instant_xml) {
- delete _instant_xml;
- }
+ delete _instant_xml;
}
void
Stateful::add_extra_xml (XMLNode& node)
{
if (_extra_xml == 0) {
- _extra_xml = new XMLNode ("extra");
+ _extra_xml = new XMLNode ("Extra");
}
_extra_xml->remove_nodes (node.name());
return 0;
}
+/** Forget about any changes to this object's properties */
+void
+Stateful::clear_changes ()
+{
+ for (OwnedPropertyList::iterator i = _properties->begin(); i != _properties->end(); ++i) {
+ i->second->clear_changes ();
+ }
+}
+
+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->get_changes_as_properties (*pl, cmd);
+ }
+
+ return pl;
+}
+
+/** Set our property values from an XML node.
+ * Derived types can call this from ::set_state() (or elsewhere)
+ * to get basic property setting done.
+ * @return IDs of properties that were changed.
+ */
+PropertyChange
+Stateful::set_values (XMLNode const & node)
+{
+ PropertyChange c;
+
+ for (OwnedPropertyList::iterator i = _properties->begin(); i != _properties->end(); ++i) {
+ if (i->second->set_value (node)) {
+ c.add (i->first);
+ }
+ }
+
+ post_set ();
+
+ return c;
+}
+
+PropertyChange
+Stateful::apply_changes (const PropertyList& property_list)
+{
+ PropertyChange c;
+ PropertyList::const_iterator p;
+
+ DEBUG_TRACE (DEBUG::Stateful, string_compose ("Stateful %1 setting properties from list of %2\n", this, property_list.size()));
+
+ for (PropertyList::const_iterator pp = property_list.begin(); pp != property_list.end(); ++pp) {
+ DEBUG_TRACE (DEBUG::Stateful, string_compose ("in plist: %1\n", pp->second->property_name()));
+ }
+
+ 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 using %2\n", p->second->property_name(), i->second->property_name())
+ );
+
+ if (apply_changes (*i->second)) {
+ c.add (i->first);
+ }
+ } else {
+ DEBUG_TRACE (DEBUG::Stateful, string_compose ("passed in property %1 not found in own property list\n",
+ i->second->property_name()));
+ }
+ }
+
+ post_set ();
+
+ send_change (c);
+
+ return c;
+}
+
+/** Add property states to an XML node.
+ * @param owner_state Node.
+ */
+void
+Stateful::add_properties (XMLNode& owner_state)
+{
+ for (OwnedPropertyList::iterator i = _properties->begin(); i != _properties->end(); ++i) {
+ i->second->get_value (owner_state);
+ }
+}
+
+void
+Stateful::add_property (PropertyBase& s)
+{
+ _properties->add (s);
+}
+
+void
+Stateful::send_change (const PropertyChange& what_changed)
+{
+ if (what_changed.empty()) {
+ return;
+ }
+
+ {
+ Glib::Mutex::Lock lm (_lock);
+ if (_frozen) {
+ _pending_changed.add (what_changed);
+ return;
+ }
+ }
+
+ PropertyChanged (what_changed);
+}
+
+void
+Stateful::suspend_property_changes ()
+{
+ _frozen++;
+}
+
+void
+Stateful::resume_property_changes ()
+{
+ PropertyChange what_changed;
+
+ {
+ Glib::Mutex::Lock lm (_lock);
+
+ if (_frozen && --_frozen > 0) {
+ return;
+ }
+
+ if (!_pending_changed.empty()) {
+ what_changed = _pending_changed;
+ _pending_changed.clear ();
+ }
+ }
+
+ mid_thaw (what_changed);
+
+ send_change (what_changed);
+}
+
+bool
+Stateful::changed() const
+{
+ for (OwnedPropertyList::const_iterator i = _properties->begin(); i != _properties->end(); ++i) {
+ if (i->second->changed()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool
+Stateful::apply_changes (const PropertyBase& prop)
+{
+ OwnedPropertyList::iterator i = _properties->find (prop.property_id());
+ if (i == _properties->end()) {
+ return false;
+ }
+
+ i->second->apply_changes (&prop);
+ return true;
+}
+
+PropertyList*
+Stateful::property_factory (const XMLNode& history_node) const
+{
+ PropertyList* prop_list = new PropertyList;
+
+ for (OwnedPropertyList::const_iterator i = _properties->begin(); i != _properties->end(); ++i) {
+ PropertyBase* prop = i->second->clone_from_xml (history_node);
+
+ if (prop) {
+ prop_list->add (prop);
+ }
+ }
+
+ return prop_list;
+}
+
+void
+Stateful::rdiff (vector<Command*>& cmds) const
+{
+ for (OwnedPropertyList::const_iterator i = _properties->begin(); i != _properties->end(); ++i) {
+ i->second->rdiff (cmds);
+ }
+}
+
+void
+Stateful::clear_owned_changes ()
+{
+ for (OwnedPropertyList::iterator i = _properties->begin(); i != _properties->end(); ++i) {
+ i->second->clear_owned_changes ();
+ }
+}
+
+
} // namespace PBD