use a static per-class signal to notify the selection object in each MidiRegionView when note items are deleted. fixes crash on cut/undo/reselect and related operations

git-svn-id: svn://localhost/ardour2/branches/3.0@7092 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2010-05-10 16:05:24 +00:00
parent 05b99bf8da
commit 37a34bb8b0
4 changed files with 45 additions and 19 deletions

View File

@ -30,6 +30,8 @@ using ARDOUR::MidiModel;
namespace Gnome {
namespace Canvas {
PBD::Signal1<void,CanvasNoteEvent*> CanvasNoteEvent::CanvasNoteEventDeleted;
/// dividing the hue circle in 16 parts, hand adjusted for equal look, courtesy Thorsten Wilms
const uint32_t CanvasNoteEvent::midi_channel_colors[16] = {
0xd32d2dff, 0xd36b2dff, 0xd3972dff, 0xd3d12dff,
@ -53,7 +55,7 @@ CanvasNoteEvent::CanvasNoteEvent(MidiRegionView& region, Item* item,
CanvasNoteEvent::~CanvasNoteEvent()
{
cerr << "Destroying CNE @ " << this << endl;
CanvasNoteEventDeleted (this);
if (_text) {
_text->hide();

View File

@ -62,6 +62,8 @@ public:
virtual ~CanvasNoteEvent();
static PBD::Signal1<void,CanvasNoteEvent*> CanvasNoteEventDeleted;
virtual void show() = 0;
virtual void hide() = 0;
virtual bool on_event(GdkEvent* ev);

View File

@ -178,6 +178,10 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptr<M
void
MidiRegionView::init (Gdk::Color const & basic_color, bool wfd)
{
CanvasNoteEvent::CanvasNoteEventDeleted.connect (note_delete_connection, MISSING_INVALIDATOR,
ui_bind (&MidiRegionView::maybe_remove_deleted_note_from_selection, this, _1),
gui_context());
if (wfd) {
midi_region()->midi_source(0)->load_model();
}
@ -789,6 +793,8 @@ MidiRegionView::redisplay_model()
MidiModel::Notes& notes (_model->notes());
_optimization_iterator = _events.begin();
cerr << "++++++++++ MIDI REdisplay\n";
for (MidiModel::Notes::iterator n = notes.begin(); n != notes.end(); ++n) {
boost::shared_ptr<NoteType> note (*n);
@ -830,6 +836,7 @@ MidiRegionView::redisplay_model()
}
}
/* remove note items that are no longer valid */
for (Events::iterator i = _events.begin(); i != _events.end(); ) {
@ -948,6 +955,8 @@ MidiRegionView::~MidiRegionView ()
{
in_destructor = true;
note_delete_connection.disconnect ();
delete _list_editor;
RegionViewGoingAway (this); /* EMIT_SIGNAL */
@ -1472,6 +1481,18 @@ MidiRegionView::next_program(CanvasProgramChange& program)
}
}
void
MidiRegionView::maybe_remove_deleted_note_from_selection (CanvasNoteEvent* cne)
{
if (_selection.empty()) {
return;
}
if (_selection.erase (cne) > 0) {
cerr << "Erased a CNE from selection\n";
}
}
void
MidiRegionView::delete_selection()
{
@ -1756,7 +1777,6 @@ MidiRegionView::add_to_selection (CanvasNoteEvent* ev)
}
if (_selection.insert (ev).second) {
cerr << "Added CNE to selection, size now " << _selection.size() << endl;
ev->selected (true);
play_midi_note ((ev)->note());
}
@ -2453,21 +2473,23 @@ MidiRegionView::cut_copy_clear (Editing::CutCopyOp op)
break;
}
start_delta_command();
if (op != Copy) {
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
switch (op) {
case Copy:
break;
case Cut:
delta_remove_note (*i);
break;
case Clear:
break;
}
}
apply_delta();
start_delta_command();
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
switch (op) {
case Copy:
break;
case Cut:
case Clear:
delta_remove_note (*i);
break;
}
}
apply_delta();
}
}
MidiCutBuffer*
@ -2475,11 +2497,8 @@ MidiRegionView::selection_as_cut_buffer () const
{
Notes notes;
cerr << "Convert selection of " << _selection.size() << " into a cut buffer\n";
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
NoteType* n = (*i)->note().get();
cerr << "CNE's note is " << n << endl;
notes.insert (boost::shared_ptr<NoteType> (new NoteType (*n)));
}

View File

@ -403,6 +403,9 @@ class MidiRegionView : public RegionView
MidiListEditor* _list_editor;
bool no_sound_notes;
PBD::ScopedConnection note_delete_connection;
void maybe_remove_deleted_note_from_selection (ArdourCanvas::CanvasNoteEvent*);
};