From 9ec7cc83d543d84816b2eb516eeb5a560a0d762d Mon Sep 17 00:00:00 2001 From: CYBERDEViLNL Date: Tue, 5 Feb 2019 15:47:41 +0100 Subject: [PATCH 1/2] =?UTF-8?q?Ghost=20notes=20improvements.=20*=20Make=20?= =?UTF-8?q?a=20copy=20of=20a=20pattern=20it=E2=80=99s=20notes=20instead=20?= =?UTF-8?q?of=20pointing=20to=20a=20pattern.=20*=20Save/load=20the=20ghost?= =?UTF-8?q?=20notes=20in/from=20the=20DOM=20document.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/PianoRoll.h | 9 ++++++- src/gui/editors/PianoRoll.cpp | 50 +++++++++++++++++++++++++++++++---- src/tracks/Pattern.cpp | 4 +-- 3 files changed, 54 insertions(+), 9 deletions(-) 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..33044cf3b7e 100644 --- a/src/tracks/Pattern.cpp +++ b/src/tracks/Pattern.cpp @@ -676,9 +676,7 @@ 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() ) + if( gui->pianoRoll()->currentPattern() && !m_pat->empty() ) { QAction * b = new QAction( embed::getIconPixmap( "ghost_note" ), tr( "Set as ghost in piano-roll" ), _cm ); From 21d637506fa3aa37b213d1461955417995b7430f Mon Sep 17 00:00:00 2001 From: CYBERDEViLNL Date: Wed, 6 Feb 2019 16:00:33 +0100 Subject: [PATCH 2/2] Better ghost notes context menu handling. --- src/tracks/Pattern.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/tracks/Pattern.cpp b/src/tracks/Pattern.cpp index 33044cf3b7e..32baf0b1484 100644 --- a/src/tracks/Pattern.cpp +++ b/src/tracks/Pattern.cpp @@ -676,20 +676,13 @@ void PatternView::constructContextMenu( QMenu * _cm ) connect( a, SIGNAL( triggered( bool ) ), this, SLOT( openInPianoRoll() ) ); - if( gui->pianoRoll()->currentPattern() && !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" ),