diff --git a/include/PianoRoll.h b/include/PianoRoll.h index 168036245ad..914d3c62305 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -92,6 +92,7 @@ class PianoRoll : public QWidget void setCurrentPattern( Pattern* newPattern ); void setGhostPattern( Pattern* newPattern ); + void loadGhostNotes( const QDomElement & de ); inline void stopRecording() { @@ -325,7 +326,13 @@ protected slots: static const QVector m_zoomLevels; Pattern* m_pattern; - Pattern* m_ghostPattern; + NoteVector m_ghostNotes; + + inline const NoteVector & ghostNotes() const + { + return m_ghostNotes; + } + QScrollBar * m_leftRightScroll; QScrollBar * m_topBottomScroll; diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 07309ec1cc6..b773724ea2f 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -452,6 +452,7 @@ void PianoRoll::reset() { m_lastNoteVolume = DefaultVolume; m_lastNotePanning = DefaultPanning; + clearGhostPattern(); } void PianoRoll::showTextFloat(const QString &text, const QPoint &pos, int timeout) @@ -605,11 +606,33 @@ PianoRoll::~PianoRoll() void PianoRoll::setGhostPattern( Pattern* newPattern ) { - m_ghostPattern = newPattern; + // Expects a pointer to a pattern or nullptr. + m_ghostNotes.clear(); if( newPattern != nullptr ) { - // make sure to always get informed about the pattern being destroyed - connect( m_ghostPattern, SIGNAL( destroyedPattern( Pattern* ) ), this, SLOT( clearGhostPattern() ) ); + for( Note *note : newPattern->notes() ) + { + Note * new_note = new Note( note->length(), note->pos(), note->key() ); + m_ghostNotes.push_back( new_note ); + } + emit ghostPatternSet( true ); + } +} + + +void PianoRoll::loadGhostNotes( const QDomElement & de ) +{ + // Load ghost notes from DOM element. + if( de.isElement() ) + { + QDomNode node = de.firstChild(); + while( !node.isNull() ) + { + Note * n = new Note; + n->restoreState( node.toElement() ); + m_ghostNotes.push_back( n ); + node = node.nextSibling(); + } emit ghostPatternSet( true ); } } @@ -3072,9 +3095,9 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) QPolygonF editHandles; // -- Begin ghost pattern - if( m_ghostPattern != nullptr && m_ghostPattern != m_pattern ) + if( !m_ghostNotes.empty() ) { - for( const Note *note : m_ghostPattern->notes() ) + for( const Note *note : m_ghostNotes ) { int len_ticks = note->length(); @@ -4459,6 +4482,21 @@ void PianoRollWindow::reset() void PianoRollWindow::saveSettings( QDomDocument & doc, QDomElement & de ) { + if( !m_editor->ghostNotes().empty() ) + { + QDomElement ghostNotesRoot = doc.createElement( "ghostnotes" ); + for( Note *note : m_editor->ghostNotes() ) + { + QDomElement ghostNoteNode = doc.createElement( "ghostnote" ); + ghostNoteNode.setAttribute( "len", note->length() ); + ghostNoteNode.setAttribute( "key", note->key() ); + ghostNoteNode.setAttribute( "pos", note->pos() ); + + ghostNotesRoot.appendChild(ghostNoteNode); + } + de.appendChild( ghostNotesRoot ); + } + MainWindow::saveWidgetState( this, de ); } @@ -4467,6 +4505,8 @@ void PianoRollWindow::saveSettings( QDomDocument & doc, QDomElement & de ) void PianoRollWindow::loadSettings( const QDomElement & de ) { + m_editor->loadGhostNotes( de.firstChildElement("ghostnotes") ); + MainWindow::restoreWidgetState( this, de ); } diff --git a/src/tracks/Pattern.cpp b/src/tracks/Pattern.cpp index a296a882161..32baf0b1484 100644 --- a/src/tracks/Pattern.cpp +++ b/src/tracks/Pattern.cpp @@ -676,22 +676,13 @@ void PatternView::constructContextMenu( QMenu * _cm ) connect( a, SIGNAL( triggered( bool ) ), this, SLOT( openInPianoRoll() ) ); - if( gui->pianoRoll()->currentPattern() && - gui->pianoRoll()->currentPattern() != m_pat && - !m_pat->empty() ) - { - QAction * b = new QAction( embed::getIconPixmap( "ghost_note" ), + QAction * b = new QAction( embed::getIconPixmap( "ghost_note" ), tr( "Set as ghost in piano-roll" ), _cm ); - _cm->insertAction( _cm->actions()[1], b ); - connect( b, SIGNAL( triggered( bool ) ), - this, SLOT( setGhostInPianoRoll() ) ); - _cm->insertSeparator( _cm->actions()[2] ); - } - else - { - _cm->insertSeparator( _cm->actions()[1] ); - } - + if( m_pat->empty() ) { b->setEnabled( false ); } + _cm->insertAction( _cm->actions()[1], b ); + connect( b, SIGNAL( triggered( bool ) ), + this, SLOT( setGhostInPianoRoll() ) ); + _cm->insertSeparator( _cm->actions()[2] ); _cm->addSeparator(); _cm->addAction( embed::getIconPixmap( "edit_erase" ),