fixes for endemic (compiler?) issues with virtual inheritance of sigc::trackable. NOTE: automation list undo/redo no longer operational, fix to follow
git-svn-id: svn://localhost/ardour2/trunk@1007 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
using namespace PBD;
|
||||
|
||||
sigc::signal<void,Controllable*> Controllable::GoingAway;
|
||||
sigc::signal<void,Controllable*> Controllable::Destroyed;
|
||||
sigc::signal<bool,Controllable*> Controllable::StartLearning;
|
||||
sigc::signal<void,Controllable*> Controllable::StopLearning;
|
||||
|
||||
|
||||
@@ -21,10 +21,9 @@
|
||||
#ifndef __lib_pbd_command_h__
|
||||
#define __lib_pbd_command_h__
|
||||
|
||||
#include <pbd/stateful.h>
|
||||
#include <pbd/destructible.h>
|
||||
#include <pbd/statefuldestructible.h>
|
||||
|
||||
class Command : public Stateful, public PBD::Destructible
|
||||
class Command : public PBD::StatefulDestructible
|
||||
{
|
||||
public:
|
||||
virtual ~Command() {}
|
||||
|
||||
@@ -6,17 +6,16 @@
|
||||
#include <sigc++/trackable.h>
|
||||
#include <sigc++/signal.h>
|
||||
|
||||
#include <pbd/stateful.h>
|
||||
#include <pbd/id.h>
|
||||
#include <pbd/statefuldestructible.h>
|
||||
|
||||
class XMLNode;
|
||||
|
||||
namespace PBD {
|
||||
|
||||
class Controllable : public virtual sigc::trackable, public Stateful {
|
||||
class Controllable : public PBD::StatefulDestructible {
|
||||
public:
|
||||
Controllable (std::string name);
|
||||
virtual ~Controllable() { GoingAway (this); }
|
||||
virtual ~Controllable() { Destroyed (this); }
|
||||
|
||||
virtual void set_value (float) = 0;
|
||||
virtual float get_value (void) const = 0;
|
||||
@@ -25,11 +24,11 @@ class Controllable : public virtual sigc::trackable, public Stateful {
|
||||
|
||||
sigc::signal<void> LearningFinished;
|
||||
|
||||
static sigc::signal<void,Controllable*> GoingAway;
|
||||
|
||||
static sigc::signal<bool,PBD::Controllable*> StartLearning;
|
||||
static sigc::signal<void,PBD::Controllable*> StopLearning;
|
||||
|
||||
static sigc::signal<void,Controllable*> Destroyed;
|
||||
|
||||
sigc::signal<void> Changed;
|
||||
|
||||
int set_state (const XMLNode&);
|
||||
|
||||
@@ -5,14 +5,22 @@
|
||||
|
||||
namespace PBD {
|
||||
|
||||
class Destructible : public virtual sigc::trackable {
|
||||
/* be very very careful using this class. it does not inherit from sigc::trackable and thus
|
||||
should only be used in multiple-inheritance situations involving another type
|
||||
that does inherit from sigc::trackable (or sigc::trackable itself)
|
||||
*/
|
||||
|
||||
class ThingWithGoingAway {
|
||||
public:
|
||||
Destructible() {}
|
||||
virtual ~Destructible () {}
|
||||
|
||||
virtual ~ThingWithGoingAway () {}
|
||||
sigc::signal<void> GoingAway;
|
||||
};
|
||||
|
||||
class Destructible : public sigc::trackable, public ThingWithGoingAway {
|
||||
public:
|
||||
virtual ~Destructible () {}
|
||||
void drop_references () const { GoingAway(); }
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -28,19 +28,11 @@ using std::endl;
|
||||
#include <pbd/command.h>
|
||||
#include <pbd/stacktrace.h>
|
||||
#include <pbd/xml++.h>
|
||||
#include <pbd/shiva.h>
|
||||
|
||||
#include <sigc++/slot.h>
|
||||
#include <typeinfo>
|
||||
|
||||
/* grrr, strict C++ says that static member functions are not C functions, but we also want
|
||||
to be able to pack this into a sigc::ptr_fun and not sigc::mem_fun, so we have to make
|
||||
it a genuine function rather than a member.
|
||||
*/
|
||||
|
||||
static void object_death (Command* mc) {
|
||||
cerr << "\n\n\n---> OBJECT DEATH FIRED FOR " << mc << endl;
|
||||
delete mc;
|
||||
}
|
||||
|
||||
/** This command class is initialized with before and after mementos
|
||||
* (from Stateful::get_state()), so undo becomes restoring the before
|
||||
* memento, and redo is restoring the after memento.
|
||||
@@ -55,8 +47,8 @@ class MementoCommand : public Command
|
||||
XMLNode *after
|
||||
)
|
||||
: obj(object), before(before), after(after) {
|
||||
cerr << "MC @ " << this << " is a " << typeid (obj_T).name() << endl;
|
||||
obj.GoingAway.connect (sigc::bind (sigc::ptr_fun (object_death), static_cast<Command*>(this)));
|
||||
/* catch destruction of the object */
|
||||
new PBD::Shiva<obj_T,MementoCommand<obj_T> > (object, *this);
|
||||
}
|
||||
|
||||
~MementoCommand () {
|
||||
|
||||
@@ -5,28 +5,96 @@
|
||||
|
||||
namespace PBD {
|
||||
|
||||
template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
|
||||
|
||||
/* named after the Hindu god Shiva, The Destroyer */
|
||||
|
||||
template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
|
||||
class Shiva {
|
||||
public:
|
||||
Shiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) {
|
||||
|
||||
/* if the emitter goes away, destroy the receiver */
|
||||
|
||||
_connection1 = emitter.GoingAway.connect
|
||||
_connection = emitter.GoingAway.connect
|
||||
(sigc::bind (sigc::mem_fun
|
||||
(*this, &Shiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy),
|
||||
&receiver));
|
||||
}
|
||||
|
||||
~Shiva() {
|
||||
forget ();
|
||||
}
|
||||
|
||||
private:
|
||||
sigc::connection _connection;
|
||||
|
||||
void destroy (ObjectToBeDestroyed* obj) {
|
||||
delete obj;
|
||||
forget ();
|
||||
}
|
||||
|
||||
void forget () {
|
||||
_connection.disconnect ();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
|
||||
class ProxyShiva {
|
||||
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;
|
||||
|
||||
_connection = emitter.GoingAway.connect
|
||||
(sigc::bind (sigc::mem_fun
|
||||
(*this, &ProxyShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy),
|
||||
&receiver));
|
||||
}
|
||||
|
||||
~ProxyShiva() {
|
||||
forget ();
|
||||
}
|
||||
|
||||
private:
|
||||
sigc::connection _connection;
|
||||
void (*_callback) (ObjectToBeDestroyed*, ObjectWithGoingAway*);
|
||||
ObjectToBeDestroyed* _callback_argument1;
|
||||
ObjectWithGoingAway* _callback_argument2;
|
||||
|
||||
void destroy (ObjectToBeDestroyed* obj) {
|
||||
/* callback must destroy obj if appropriate, not done here */
|
||||
_callback (obj, _callback_argument2);
|
||||
forget ();
|
||||
}
|
||||
|
||||
void forget () {
|
||||
_connection.disconnect ();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
|
||||
class PairedShiva {
|
||||
public:
|
||||
PairedShiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) {
|
||||
|
||||
/* if the emitter goes away, destroy the receiver */
|
||||
|
||||
_connection1 = emitter.GoingAway.connect
|
||||
(sigc::bind (sigc::mem_fun
|
||||
(*this, &PairedShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy),
|
||||
&receiver));
|
||||
|
||||
/* if the receiver goes away, forget all this nonsense */
|
||||
|
||||
_connection2 = receiver.GoingAway.connect
|
||||
(sigc::mem_fun (*this, &Shiva<ObjectWithGoingAway,ObjectToBeDestroyed>::forget));
|
||||
(sigc::mem_fun (*this, &PairedShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::forget));
|
||||
}
|
||||
|
||||
~Shiva() {
|
||||
~PairedShiva() {
|
||||
forget ();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,21 @@
|
||||
#include <pbd/destructible.h>
|
||||
|
||||
namespace PBD {
|
||||
|
||||
class StatefulDestructible : public Stateful, public Destructible
|
||||
{
|
||||
};
|
||||
|
||||
/* be very very careful using this class. it does not inherit from sigc::trackable and thus
|
||||
should only be used in multiple-inheritance situations involving another type
|
||||
that does inherit from sigc::trackable (or sigc::trackable itself)
|
||||
*/
|
||||
|
||||
class StatefulThingWithGoingAway : public Stateful, public ThingWithGoingAway
|
||||
{
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* __pbd_stateful_destructible_h__ */
|
||||
|
||||
@@ -70,6 +70,8 @@ class UndoTransaction : public Command
|
||||
struct timeval _timestamp;
|
||||
std::string _name;
|
||||
bool _clearing;
|
||||
|
||||
friend void command_death (UndoTransaction*, Command *);
|
||||
};
|
||||
|
||||
class UndoHistory
|
||||
|
||||
@@ -24,31 +24,13 @@
|
||||
|
||||
#include <pbd/undo.h>
|
||||
#include <pbd/xml++.h>
|
||||
#include <pbd/shiva.h>
|
||||
|
||||
#include <sigc++/bind.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace sigc;
|
||||
|
||||
/* grrr, strict C++ says that static member functions are not C functions, but we also want
|
||||
to be able to pack this into a sigc::ptr_fun and not sigc::mem_fun, so we have to make
|
||||
it a genuine function rather than a member.
|
||||
*/
|
||||
|
||||
static void command_death (UndoTransaction* ut, Command* c)
|
||||
{
|
||||
if (ut->clearing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ut->remove_command (c);
|
||||
|
||||
if (ut->empty()) {
|
||||
delete ut;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UndoTransaction::UndoTransaction ()
|
||||
{
|
||||
_clearing = false;
|
||||
@@ -68,6 +50,20 @@ UndoTransaction::~UndoTransaction ()
|
||||
clear ();
|
||||
}
|
||||
|
||||
void
|
||||
command_death (UndoTransaction* ut, Command* c)
|
||||
{
|
||||
if (ut->clearing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ut->remove_command (c);
|
||||
|
||||
if (ut->empty()) {
|
||||
delete ut;
|
||||
}
|
||||
}
|
||||
|
||||
UndoTransaction&
|
||||
UndoTransaction::operator= (const UndoTransaction& rhs)
|
||||
{
|
||||
@@ -81,7 +77,8 @@ UndoTransaction::operator= (const UndoTransaction& rhs)
|
||||
void
|
||||
UndoTransaction::add_command (Command *const action)
|
||||
{
|
||||
action->GoingAway.connect (bind (sigc::ptr_fun (command_death), this, const_cast<Command*>(action)));
|
||||
/* catch death */
|
||||
new PBD::ProxyShiva<Command,UndoTransaction> (*action, *this, &command_death);
|
||||
actions.push_back (action);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user