piano roll improvements

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@1860 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Andrew Kelley
2008-11-30 05:31:05 +00:00
parent 96bad01415
commit c50ca0eb9b
5 changed files with 194 additions and 56 deletions

View File

@@ -65,12 +65,12 @@ note::note( const midiTime & _length, const midiTime & _pos,
note::note( const note & _note ) :
serializingObject( _note ),
m_selected( _note.m_selected ),
m_key( _note.m_key),
m_volume( _note.m_volume ),
m_panning( _note.m_panning ),
m_length( _note.m_length ),
m_pos( _note.m_pos ),
m_selected( _note.m_selected )
m_pos( _note.m_pos )
{
m_detuning = sharedObject::ref( _note.m_detuning );
}

View File

@@ -147,6 +147,8 @@ pianoRoll::pianoRoll( void ) :
m_startKey( INITIAL_START_KEY ),
m_lastKey( 0 ),
m_editMode( ModeDraw ),
m_mouseDownLeft( false ),
m_mouseDownRight( false ),
m_scrollBack( false )
{
// init pixmaps
@@ -291,17 +293,11 @@ pianoRoll::pianoRoll( void ) :
m_toolBar );
m_selectButton->setCheckable( true );
m_moveButton = new toolButton( embed::getIconPixmap( "edit_move" ),
tr( "Move selection mode (Shift+M)" ),
this, SLOT( moveButtonToggled() ),
m_toolBar );
m_moveButton->setCheckable( true );
QButtonGroup * tool_button_group = new QButtonGroup( this );
tool_button_group->addButton( m_drawButton );
tool_button_group->addButton( m_eraseButton );
tool_button_group->addButton( m_selectButton );
tool_button_group->addButton( m_moveButton );
tool_button_group->setExclusive( true );
m_drawButton->setWhatsThis(
@@ -320,11 +316,6 @@ pianoRoll::pianoRoll( void ) :
"if you want to cut, copy, paste, delete or move "
"notes. You can also press 'Shift+S' on your keyboard "
"to activate this mode." ) );
m_moveButton->setWhatsThis(
tr( "Click here and move-mode will be activated. In this "
"mode you can move the notes you selected in select-"
"mode. You can also press 'Shift+M' on your keyboard "
"to activate this mode." ) );
m_cutButton = new toolButton( embed::getIconPixmap( "edit_cut" ),
tr( "Cut selected notes (Ctrl+X)" ),
@@ -432,7 +423,6 @@ pianoRoll::pianoRoll( void ) :
tb_layout->addWidget( m_drawButton );
tb_layout->addWidget( m_eraseButton );
tb_layout->addWidget( m_selectButton );
tb_layout->addWidget( m_moveButton );
tb_layout->addSpacing( 10 );
tb_layout->addWidget( m_cutButton );
tb_layout->addWidget( m_copyButton );
@@ -691,8 +681,58 @@ void pianoRoll::closeEvent( QCloseEvent * _ce )
_ce->ignore();
}
void pianoRoll::shiftSemiTone(int amount) // shift notes by amount semitones
{
bool useAllNotes = ! isSelection();
const noteVector & notes = m_pattern->notes();
for( noteVector::const_iterator it = notes.begin(); it != notes.end(); ++it)
{
// if none are selected, move all notes, otherwise
// only move selected notes
if( useAllNotes || ( *it )->getSelected() )
{
( *it )->setKey( ( *it )->key() + amount );
}
}
// we modified the song
update();
engine::getSongEditor()->update();
}
void pianoRoll::shiftPos(int amount) //shift notes pos by amount
{
bool useAllNotes = ! isSelection();
const noteVector & notes = m_pattern->notes();
for( noteVector::const_iterator it = notes.begin(); it != notes.end(); ++it)
{
// if none are selected, move all notes, otherwise
// only move selected notes
if( useAllNotes || ( *it )->getSelected() )
{
( *it )->setPos( ( *it )->pos() + amount );
}
}
// we modified the song
update();
engine::getSongEditor()->update();
}
bool pianoRoll::isSelection() const // are any notes selected?
{
const noteVector & notes = m_pattern->notes();
for( noteVector::const_iterator it = notes.begin(); it != notes.end(); ++it)
{
if( ( *it )->getSelected() )
{
return true;
}
}
return false;
}
void pianoRoll::keyPressEvent( QKeyEvent * _ke )
{
@@ -711,28 +751,84 @@ void pianoRoll::keyPressEvent( QKeyEvent * _ke )
switch( _ke->key() )
{
case Qt::Key_Up:
m_topBottomScroll->setValue(
m_topBottomScroll->value() - 1 );
if( _ke->modifiers() & Qt::ControlModifier )
{
// shift selection up an octave
// if nothing selected, shift _everything_
shiftSemiTone( +12 );
}
else
{
// scroll
m_topBottomScroll->setValue(
m_topBottomScroll->value() - cm_scrollAmtVert );
}
break;
case Qt::Key_Down:
m_topBottomScroll->setValue(
m_topBottomScroll->value() + 1 );
if( _ke->modifiers() & Qt::ControlModifier )
{
// shift selection down an octave
// if nothing selected, shift _everything_
shiftSemiTone( -12 );
}
else
{
// scroll
m_topBottomScroll->setValue(
m_topBottomScroll->value() + cm_scrollAmtVert );
}
break;
case Qt::Key_Left:
{
if( ( m_timeLine->pos() -= 16 ) < 0 )
if( _ke->modifiers() & Qt::ControlModifier )
{
m_timeLine->pos().setTicks( 0 );
// move time ticker
if( ( m_timeLine->pos() -= 16 ) < 0 )
{
m_timeLine->pos().setTicks( 0 );
}
m_timeLine->updatePosition();
}
else if( _ke->modifiers() & Qt::ShiftModifier )
{
// move notes
bool quantized = ! (_ke->modifiers() & Qt::AltModifier);
int amt = quantized ? quantization() : 1;
shiftPos( -amt );
}
else
{
// scroll
m_leftRightScroll->setValue(
m_leftRightScroll->value() - cm_scrollAmtHoriz );
}
m_timeLine->updatePosition();
break;
}
case Qt::Key_Right:
{
m_timeLine->pos() += 16;
m_timeLine->updatePosition();
if( _ke->modifiers() & Qt::ControlModifier )
{
// move time ticker
m_timeLine->pos() += 16;
m_timeLine->updatePosition();
}
else if( _ke->modifiers() & Qt::ShiftModifier )
{
// move notes
bool quantized = ! (_ke->modifiers() & Qt::AltModifier);
int amt = quantized ? quantization() : 1;
shiftPos( +amt );
}
else
{
// scroll
m_leftRightScroll->setValue(
m_leftRightScroll->value() + cm_scrollAmtHoriz );
}
break;
}
@@ -815,17 +911,6 @@ void pianoRoll::keyPressEvent( QKeyEvent * _ke )
}
break;
case Qt::Key_M:
if( _ke->modifiers() & Qt::ShiftModifier )
{
m_moveButton->setChecked( true );
}
else
{
_ke->ignore();
}
break;
case Qt::Key_Delete:
deleteSelectedNotes();
break;
@@ -1065,6 +1150,10 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
pattern::MelodyPattern );
// then set new note
// clear selection and select this new note
clearSelectedNotes();
// +32 to quanitize the note correctly when placing notes with
// the mouse. We do this here instead of in note.quantized
// because live notes should still be quantized at the half.
@@ -1072,7 +1161,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
midiTime note_len( newNoteLen() );
note new_note( note_len, note_pos, key_num );
new_note.setSelected( true );
note * created_new_note =
m_pattern->addNote( new_note );
@@ -1137,7 +1226,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
m_editMode == ModeErase )
{
// erase single note
m_mouseDownRight = true;
play_note = false;
if( it != notes.end() )
{
@@ -1170,15 +1259,6 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
// appears in wrong spot on mousedown
mouseMoveEvent( _me );
}
else if( _me->button() == Qt::RightButton &&
m_editMode == ModeSelect )
{
// when clicking right in select-move, we
// switch to move-mode
m_moveButton->setChecked( true );
play_note = false;
}
else if( _me->button() == Qt::LeftButton &&
m_editMode == ModeMove )
{
@@ -1189,6 +1269,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
m_moveStartKey = key_num;
m_action = ActionMoveSelection;
m_mouseDownLeft = true;
play_note = false;
engine::getSong()->setModified();
@@ -1312,6 +1393,19 @@ void pianoRoll::computeSelectedNotes(bool shift)
void pianoRoll::mouseReleaseEvent( QMouseEvent * _me )
{
bool mustRepaint = false;
if( _me->button() & Qt::LeftButton )
{
m_mouseDownLeft = false;
mustRepaint = true;
}
if( _me->button() & Qt::RightButton )
{
m_mouseDownRight = false;
mustRepaint = true;
}
if( _me->button() & Qt::LeftButton &&
m_editMode == ModeSelect &&
m_action == ActionSelectNotes )
@@ -1356,6 +1450,11 @@ void pianoRoll::mouseReleaseEvent( QMouseEvent * _me )
{
QApplication::restoreOverrideCursor();
}
if( mustRepaint )
{
repaint();
}
}
@@ -2373,7 +2472,21 @@ void pianoRoll::paintEvent( QPaintEvent * _pe )
// draw current edit-mode-icon below the cursor
switch( m_editMode )
{
case ModeDraw: cursor = s_toolDraw; break;
case ModeDraw:
if( m_mouseDownRight )
{
cursor = s_toolErase;
}
else if( m_action == ActionMoveSelection ||
m_action == ActionMoveNote )
{
cursor = s_toolMove;
}
else
{
cursor = s_toolDraw;
}
break;
case ModeErase: cursor = s_toolErase; break;
case ModeSelect: cursor = s_toolSelect; break;
case ModeMove: cursor = s_toolMove; break;