-/*
+/*
Copyright (C) 2001 Brett Viren & Paul Davis
This program is free software; you can redistribute it and/or modify
#include <sstream>
#include <time.h>
-#include <pbd/undo.h>
-#include <pbd/xml++.h>
+#include "pbd/undo.h"
+#include "pbd/xml++.h"
#include <sigc++/bind.h>
: Command(rhs._name)
, _clearing(false)
{
+ _timestamp = rhs._timestamp;
clear ();
actions.insert(actions.end(),rhs.actions.begin(),rhs.actions.end());
}
UndoTransaction::~UndoTransaction ()
{
- GoingAway ();
+ drop_references ();
clear ();
}
-void
+void
command_death (UndoTransaction* ut, Command* c)
{
if (ut->clearing()) {
}
}
-UndoTransaction&
+UndoTransaction&
UndoTransaction::operator= (const UndoTransaction& rhs)
{
if (this == &rhs) return *this;
}
void
-UndoTransaction::add_command (Command *const action)
+UndoTransaction::add_command (Command *const cmd)
{
/* catch death of command (e.g. caused by death of object to
- which it refers.
+ which it refers. command_death() is a normal static function
+ so there is no need to manage this connection.
*/
- shivas.push_back (new PBD::ProxyShiva<Command,UndoTransaction> (*action, *this, &command_death));
- actions.push_back (action);
+
+ cmd->DropReferences.connect_same_thread (*this, boost::bind (&command_death, this, cmd));
+ actions.push_back (cmd);
}
void
actions.remove (action);
}
-void
-UndoTransaction::about_to_explicitly_delete ()
-{
- /* someone is going to call our destructor and its not Shiva,
- the god of destruction and chaos. This happens when an UndoHistory
- is pruning itself. we must remove Shivas to avoid the god
- striking us down a second time, unnecessarily and illegally.
- */
-
- for (list<PBD::ProxyShiva<Command,UndoTransaction>*>::iterator i = shivas.begin(); i != shivas.end(); ++i) {
- delete *i;
- }
- shivas.clear ();
-}
-
bool
UndoTransaction::empty () const
{
XMLNode &UndoTransaction::get_state()
{
XMLNode *node = new XMLNode ("UndoTransaction");
- stringstream ss;
- ss << _timestamp.tv_sec;
- node->add_property("tv_sec", ss.str());
- ss.str("");
- ss << _timestamp.tv_usec;
- node->add_property("tv_usec", ss.str());
- node->add_property("name", _name);
+ node->set_property("tv-sec", (int64_t)_timestamp.tv_sec);
+ node->set_property("tv-usec", (int64_t)_timestamp.tv_usec);
+ node->set_property("name", _name);
list<Command*>::iterator it;
for (it=actions.begin(); it!=actions.end(); it++)
return *node;
}
+class UndoRedoSignaller {
+public:
+ UndoRedoSignaller (UndoHistory& uh)
+ : _history (uh) {
+ _history.BeginUndoRedo();
+ }
+ ~UndoRedoSignaller() {
+ _history.EndUndoRedo();
+ }
+
+private:
+ UndoHistory& _history;
+};
+
UndoHistory::UndoHistory ()
{
_clearing = false;
while (cnt--) {
ut = UndoList.front();
UndoList.pop_front ();
- ut->about_to_explicitly_delete ();
delete ut;
}
}
{
uint32_t current_depth = UndoList.size();
- ut->GoingAway.connect (bind (mem_fun (*this, &UndoHistory::remove), ut));
+ 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
UndoTransaction* ut;
ut = UndoList.front ();
UndoList.pop_front ();
- ut->about_to_explicitly_delete ();
delete ut;
}
}
UndoList.push_back (ut);
+ /* Adding a transacrion makes the redo list meaningless. */
+ _clearing = true;
+ for (std::list<UndoTransaction*>::iterator i = RedoList.begin(); i != RedoList.end(); ++i) {
+ delete *i;
+ }
+ RedoList.clear ();
+ _clearing = false;
/* we are now owners of the transaction and must delete it when finished with it */
void
UndoHistory::undo (unsigned int n)
{
- while (n--) {
- if (UndoList.size() == 0) {
- return;
+ if (n == 0) {
+ return;
+ }
+
+ {
+ UndoRedoSignaller exception_safe_signaller (*this);
+
+ while (n--) {
+ if (UndoList.size() == 0) {
+ return;
+ }
+ UndoTransaction* ut = UndoList.back ();
+ UndoList.pop_back ();
+ ut->undo ();
+ RedoList.push_back (ut);
}
- UndoTransaction* ut = UndoList.back ();
- UndoList.pop_back ();
- ut->undo ();
- RedoList.push_back (ut);
}
Changed (); /* EMIT SIGNAL */
void
UndoHistory::redo (unsigned int n)
{
- while (n--) {
- if (RedoList.size() == 0) {
- return;
+ if (n == 0) {
+ return;
+ }
+
+ {
+ UndoRedoSignaller exception_safe_signaller (*this);
+
+ while (n--) {
+ if (RedoList.size() == 0) {
+ return;
+ }
+ UndoTransaction* ut = RedoList.back ();
+ RedoList.pop_back ();
+ ut->redo ();
+ UndoList.push_back (ut);
}
- UndoTransaction* ut = RedoList.back ();
- RedoList.pop_back ();
- ut->redo ();
- UndoList.push_back (ut);
}
Changed (); /* EMIT SIGNAL */
UndoHistory::clear_redo ()
{
_clearing = true;
+ for (std::list<UndoTransaction*>::iterator i = RedoList.begin(); i != RedoList.end(); ++i) {
+ delete *i;
+ }
RedoList.clear ();
_clearing = false;
UndoHistory::clear_undo ()
{
_clearing = true;
+ for (std::list<UndoTransaction*>::iterator i = UndoList.begin(); i != UndoList.end(); ++i) {
+ delete *i;
+ }
UndoList.clear ();
_clearing = false;
Changed (); /* EMIT SIGNAL */
}
-XMLNode&
+XMLNode&
UndoHistory::get_state (int32_t depth)
{
XMLNode *node = new XMLNode ("UndoHistory");