13
0

Fix various MIDI List editor issues (#9457)

* Fix crash when inserting note to empty region
* Consistently use fine-grained modifier
* Don't allow to edit BBT as text field
  This is currently not supported.
* Fix GTK_IS_CELL_EDITABLE assertions (Tab to next)
This commit is contained in:
Robin Gareus 2023-09-24 14:08:05 +02:00
parent 1386a96af0
commit ad24d397f5
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (C) 2009-2015 David Robillard <d@drobilla.net> * Copyright (C) 2009-2015 David Robillard <d@drobilla.net>
* Copyright (C) 2009-2017 Paul Davis <paul@linuxaudiosystems.com> * Copyright (C) 2009-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2014-2016 Robin Gareus <robin@gareus.org> * Copyright (C) 2014-2023 Robin Gareus <robin@gareus.org>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -129,7 +129,9 @@ MidiListEditor::MidiListEditor (Session* s, std::shared_ptr<MidiRegion> r, std::
view.get_selection()->set_mode (SELECTION_MULTIPLE); view.get_selection()->set_mode (SELECTION_MULTIPLE);
view.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &MidiListEditor::selection_changed)); view.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &MidiListEditor::selection_changed));
for (int i = 0; i < 6; ++i) { /* Editing the first column (BBT) as text is currently not supported
* -> use editable AudioClock, implement parse_as_bbt */
for (int i = 1; i < 6; ++i) {
CellRendererText* renderer = dynamic_cast<CellRendererText*>(view.get_column_cell_renderer (i)); CellRendererText* renderer = dynamic_cast<CellRendererText*>(view.get_column_cell_renderer (i));
TreeViewColumn* col = view.get_column (i); TreeViewColumn* col = view.get_column (i);
@ -207,7 +209,10 @@ MidiListEditor::scroll_event (GdkEventScroll* ev)
switch (colnum) { switch (colnum) {
case 0: case 0:
if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) { /* This is dangerous. Changing position with the mouse-wheel can reorder
* notes. The mouse-position does not change and then affect different notes.
*/
if (Keyboard::modifier_state_equals (ev->state, Keyboard::GainFineScaleModifier)) {
beat_delta = Temporal::Beats::ticks (Temporal::ticks_per_beat / 64); beat_delta = Temporal::Beats::ticks (Temporal::ticks_per_beat / 64);
} else { } else {
beat_delta = Temporal::Beats (1, 0); beat_delta = Temporal::Beats (1, 0);
@ -250,7 +255,7 @@ MidiListEditor::scroll_event (GdkEventScroll* ev)
break; break;
case 5: case 5:
if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) { if (Keyboard::modifier_state_equals (ev->state, Keyboard::GainFineScaleModifier)) {
beat_delta = Temporal::Beats::ticks (Temporal::ticks_per_beat / 64); beat_delta = Temporal::Beats::ticks (Temporal::ticks_per_beat / 64);
} else { } else {
beat_delta = Temporal::Beats (1, 0); beat_delta = Temporal::Beats (1, 0);
@ -397,13 +402,18 @@ MidiListEditor::key_press (GdkEventKey* ev)
} }
if (colnum >= 5) { if (colnum >= 5) {
/* wrap to next line */ /* wrap to next line */
/* XXX never reached. Editing Length shows a dropdown menu,
* which returns edit focus to the dialog.
*/
colnum = 0; colnum = 0;
path.next(); path.next();
} else { } else {
colnum++; colnum++;
} }
col = view.get_column (colnum); if (!path.empty ()) {
view.set_cursor (path, *col, true); col = view.get_column (colnum);
view.set_cursor (path, *col, true);
}
ret = true; ret = true;
} }
break; break;
@ -417,8 +427,10 @@ MidiListEditor::key_press (GdkEventKey* ev)
editing_editable->editing_done (); editing_editable->editing_done ();
} }
path.prev (); path.prev ();
col = view.get_column (colnum); if (!path.empty ()) {
view.set_cursor (path, *col, true); col = view.get_column (colnum);
view.set_cursor (path, *col, true);
}
ret = true; ret = true;
} }
break; break;
@ -432,8 +444,10 @@ MidiListEditor::key_press (GdkEventKey* ev)
editing_editable->editing_done (); editing_editable->editing_done ();
} }
path.next (); path.next ();
col = view.get_column (colnum); if (!path.empty ()) {
view.set_cursor (path, *col, true); col = view.get_column (colnum);
view.set_cursor (path, *col, true);
}
ret = true; ret = true;
} }
break; break;
@ -461,21 +475,26 @@ MidiListEditor::key_release (GdkEventKey* ev)
switch (ev->keyval) { switch (ev->keyval) {
case GDK_Insert: case GDK_Insert:
/* add a new note to the model, based on the note at the cursor /* add a new note to the model, based on the note at the cursor pos */
* pos
*/
view.get_cursor (path, col); view.get_cursor (path, col);
iter = model->get_iter (path); iter = model->get_iter (path);
cmd = m->new_note_diff_command (_("insert new note")); cmd = m->new_note_diff_command (_("insert new note"));
note = (*iter)[columns._note]; if (iter) {
copy.reset (new NoteType (*note.get())); note = (*iter)[columns._note];
copy.reset (new NoteType (*note.get()));
} else {
Temporal::Beats pos = Temporal::TempoMap::use()->quarters_at_sample (region->start().samples());
copy.reset (new NoteType (0, pos, Temporal::Beats (1, 0), 60, 100));
}
cmd->add (copy); cmd->add (copy);
m->apply_diff_command_as_commit (*_session, cmd); m->apply_diff_command_as_commit (*_session, cmd);
/* model has been redisplayed by now */ /* model has been redisplayed by now */
path.next (); path.next ();
/* select, start editing column 2 (note) */ if (!path.empty ()) {
col = view.get_column (2); /* select, start editing column 2 (note) */
view.set_cursor (path, *col, true); col = view.get_column (2);
view.set_cursor (path, *col, true);
}
break; break;
case GDK_Delete: case GDK_Delete: