MIDIClock_SlaveTest: first working testcase
[ardour.git] / libs / pbd / undo.cc
index aeff37cce72e3f6dc70a9136b97e8df8a1f218fe..8d6510191372f1a122f0eb0ae78bbd248bc613a6 100644 (file)
 #include <iostream>
 #include <string>
 #include <sstream>
+#include <time.h>
 
-#include <pbd/undo.h>
-#include <pbd/xml++.h>
-#include <pbd/shiva.h>
+#include "pbd/undo.h"
+#include "pbd/xml++.h"
 
 #include <sigc++/bind.h>
 
@@ -34,10 +34,12 @@ using namespace sigc;
 UndoTransaction::UndoTransaction ()
        : _clearing(false)
 {
+       gettimeofday (&_timestamp, 0);
 }
 
 UndoTransaction::UndoTransaction (const UndoTransaction& rhs)
        : Command(rhs._name)
+       , PBD::ScopedConnectionList ()
        , _clearing(false)
 {
        clear ();
@@ -46,7 +48,7 @@ UndoTransaction::UndoTransaction (const UndoTransaction& rhs)
 
 UndoTransaction::~UndoTransaction ()
 {
-       GoingAway ();
+       drop_references ();
        clear ();
 }
 
@@ -77,8 +79,12 @@ UndoTransaction::operator= (const UndoTransaction& rhs)
 void
 UndoTransaction::add_command (Command *const action)
 {
-       /* catch death */
-       new PBD::ProxyShiva<Command,UndoTransaction> (*action, *this, &command_death);
+       /* catch death of command (e.g. caused by death of object to
+          which it refers. command_death() is a normal static function
+          so there is no need to manage this connection.
+        */
+
+       action->DropReferences.connect_same_thread (*this, boost::bind (&command_death, this, action));
        actions.push_back (action);
 }
 
@@ -152,27 +158,57 @@ UndoHistory::UndoHistory ()
 }
 
 void
-UndoHistory::set_depth (int32_t d)
+UndoHistory::set_depth (uint32_t d)
 {
+       UndoTransaction* ut;
+       uint32_t current_depth = UndoList.size();
+
        _depth = d;
 
-       while (_depth > 0 && UndoList.size() > (uint32_t) _depth) {
-               UndoList.pop_front ();
+       if (d > current_depth) {
+               /* not even transactions to meet request */
+               return;
+       }
+
+       if (_depth > 0) {
+
+               uint32_t cnt = current_depth - d;
+
+               while (cnt--) {
+                       ut = UndoList.front();
+                       UndoList.pop_front ();
+                       delete ut;
+               }
        }
 }
 
 void
 UndoHistory::add (UndoTransaction* const ut)
 {
-       ut->GoingAway.connect (bind (mem_fun (*this, &UndoHistory::remove), ut));
+       uint32_t current_depth = UndoList.size();
+
+       ut->DropReferences.connect_same_thread (*this, boost::bind (&UndoHistory::remove, this, ut));
+
+       /* if the current undo history is larger than or equal to the currently
+          requested depth, then pop off at least 1 element to make space
+          at the back for new one.
+       */
 
-       while (_depth > 0 && UndoList.size() > (uint32_t) _depth) {
-               UndoList.pop_front ();
+       if ((_depth > 0) && current_depth && (current_depth >= _depth)) {
+
+               uint32_t cnt = 1 + (current_depth - _depth);
+
+               while (cnt--) {
+                       UndoTransaction* ut;
+                       ut = UndoList.front ();
+                       UndoList.pop_front ();
+                       delete ut;
+               }
        }
 
        UndoList.push_back (ut);
 
-       /* we are now owners of the transaction */
+       /* we are now owners of the transaction and must delete it when finished with it */
 
        Changed (); /* EMIT SIGNAL */
 }