mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-19 20:06:09 +01:00
fix up monumental botch job regarding undo history/object/command management
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@4274 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
2542b776c5
commit
71ac083429
4 changed files with 41 additions and 15 deletions
|
|
@ -47,7 +47,7 @@ class MementoCommand : public Command
|
|||
)
|
||||
: obj(object), before(before), after(after) {
|
||||
/* catch destruction of the object */
|
||||
new PBD::Shiva<obj_T,MementoCommand<obj_T> > (object, *this);
|
||||
new PBD::PairedShiva<obj_T,MementoCommand<obj_T> > (object, *this);
|
||||
}
|
||||
|
||||
~MementoCommand () {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ namespace PBD {
|
|||
/* named after the Hindu god Shiva, The Destroyer */
|
||||
|
||||
template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
|
||||
class Shiva {
|
||||
class Shiva : public sigc::trackable
|
||||
{
|
||||
public:
|
||||
Shiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) {
|
||||
|
||||
|
|
@ -58,15 +59,15 @@ class Shiva {
|
|||
};
|
||||
|
||||
template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
|
||||
class ProxyShiva {
|
||||
class ProxyShiva : public sigc::trackable
|
||||
{
|
||||
public:
|
||||
ProxyShiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver, void (*callback)(ObjectToBeDestroyed*, ObjectWithGoingAway*)) {
|
||||
|
||||
|
||||
/* if the emitter goes away, destroy the receiver */
|
||||
|
||||
_callback = callback;
|
||||
_callback_argument1 = &receiver;
|
||||
_callback_argument2 = &emitter;
|
||||
_callback_argument = &emitter;
|
||||
|
||||
_connection = emitter.GoingAway.connect
|
||||
(sigc::bind (sigc::mem_fun
|
||||
|
|
@ -74,19 +75,18 @@ class ProxyShiva {
|
|||
&receiver));
|
||||
}
|
||||
|
||||
~ProxyShiva() {
|
||||
~ProxyShiva () {
|
||||
forget ();
|
||||
}
|
||||
|
||||
private:
|
||||
sigc::connection _connection;
|
||||
void (*_callback) (ObjectToBeDestroyed*, ObjectWithGoingAway*);
|
||||
ObjectToBeDestroyed* _callback_argument1;
|
||||
ObjectWithGoingAway* _callback_argument2;
|
||||
ObjectWithGoingAway* _callback_argument;
|
||||
|
||||
void destroy (ObjectToBeDestroyed* obj) {
|
||||
/* callback must destroy obj if appropriate, not done here */
|
||||
_callback (obj, _callback_argument2);
|
||||
_callback (obj, _callback_argument);
|
||||
forget ();
|
||||
}
|
||||
|
||||
|
|
@ -96,7 +96,8 @@ class ProxyShiva {
|
|||
};
|
||||
|
||||
template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
|
||||
class PairedShiva {
|
||||
class PairedShiva : public sigc::trackable
|
||||
{
|
||||
public:
|
||||
PairedShiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) {
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <sigc++/bind.h>
|
||||
#include <sys/time.h>
|
||||
#include <pbd/command.h>
|
||||
#include <pbd/shiva.h>
|
||||
|
||||
typedef sigc::slot<void> UndoAction;
|
||||
|
||||
|
|
@ -36,7 +37,6 @@ class UndoTransaction : public Command
|
|||
UndoTransaction ();
|
||||
UndoTransaction (const UndoTransaction&);
|
||||
UndoTransaction& operator= (const UndoTransaction&);
|
||||
~UndoTransaction ();
|
||||
|
||||
void clear ();
|
||||
bool empty() const;
|
||||
|
|
@ -66,11 +66,18 @@ class UndoTransaction : public Command
|
|||
|
||||
private:
|
||||
std::list<Command*> actions;
|
||||
std::list<PBD::ProxyShiva<Command,UndoTransaction>*> shivas;
|
||||
struct timeval _timestamp;
|
||||
std::string _name;
|
||||
bool _clearing;
|
||||
|
||||
friend void command_death (UndoTransaction*, Command *);
|
||||
|
||||
friend class UndoHistory;
|
||||
|
||||
~UndoTransaction ();
|
||||
void about_to_explicitly_delete ();
|
||||
|
||||
};
|
||||
|
||||
class UndoHistory : public sigc::trackable
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include <pbd/undo.h>
|
||||
#include <pbd/xml++.h>
|
||||
#include <pbd/shiva.h>
|
||||
|
||||
#include <sigc++/bind.h>
|
||||
|
||||
|
|
@ -78,8 +77,10 @@ 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.
|
||||
*/
|
||||
shivas.push_back (new PBD::ProxyShiva<Command,UndoTransaction> (*action, *this, &command_death));
|
||||
actions.push_back (action);
|
||||
}
|
||||
|
||||
|
|
@ -89,6 +90,21 @@ UndoTransaction::remove_command (Command* const action)
|
|||
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
|
||||
{
|
||||
|
|
@ -172,6 +188,7 @@ UndoHistory::set_depth (uint32_t d)
|
|||
while (cnt--) {
|
||||
ut = UndoList.front();
|
||||
UndoList.pop_front ();
|
||||
ut->about_to_explicitly_delete ();
|
||||
delete ut;
|
||||
}
|
||||
}
|
||||
|
|
@ -197,6 +214,7 @@ UndoHistory::add (UndoTransaction* const ut)
|
|||
UndoTransaction* ut;
|
||||
ut = UndoList.front ();
|
||||
UndoList.pop_front ();
|
||||
ut->about_to_explicitly_delete ();
|
||||
delete ut;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue