From e1adfc3952389f0e6c18c3bf7daef40c4ca72481 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Fri, 1 Mar 2019 09:00:46 +0100 Subject: [PATCH] TCO drag: Fix Ctrl+Drag crash Fix some assumptions that source and target of a drag actions are the same track container. Instead of looking up necessary information (track name, type and container id) by track index, add it to the metadata. Refactor canPasteSelection to take QDropEvent instead of the drop event's QMimeData. Coincidentally, this fixes the method to be consistent with its documentation. Fixes #4844 --- include/Track.h | 2 +- src/core/Track.cpp | 27 ++++++++++++++++++--------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/include/Track.h b/include/Track.h index 00ee5d0a6..f548168b7 100644 --- a/include/Track.h +++ b/include/Track.h @@ -341,7 +341,7 @@ public: } } - bool canPasteSelection( MidiTime tcoPos, const QMimeData * mimeData ); + bool canPasteSelection( MidiTime tcoPos, const QDropEvent *de ); bool pasteSelection( MidiTime tcoPos, QDropEvent * de ); MidiTime endPosition( const MidiTime & posStart ); diff --git a/src/core/Track.cpp b/src/core/Track.cpp index b300d94a3..cd1d23b16 100644 --- a/src/core/Track.cpp +++ b/src/core/Track.cpp @@ -497,7 +497,7 @@ void TrackContentObjectView::dragEnterEvent( QDragEnterEvent * dee ) { TrackContentWidget * tcw = getTrackView()->getTrackContentWidget(); MidiTime tcoPos = MidiTime( m_tco->startPosition().getTact(), 0 ); - if( tcw->canPasteSelection( tcoPos, dee->mimeData() ) == false ) + if( tcw->canPasteSelection( tcoPos, dee ) == false ) { dee->ignore(); } @@ -602,9 +602,12 @@ DataFile TrackContentObjectView::createTCODataFiles( it != tcoViews.end(); ++it ) { // Insert into the dom under the "tcos" element - int trackIndex = tc->tracks().indexOf( ( *it )->m_trackView->getTrack() ); + Track* tcoTrack = ( *it )->m_trackView->getTrack(); + int trackIndex = tc->tracks().indexOf( tcoTrack ); QDomElement tcoElement = dataFile.createElement( "tco" ); tcoElement.setAttribute( "trackIndex", trackIndex ); + tcoElement.setAttribute( "trackType", tcoTrack->type() ); + tcoElement.setAttribute( "trackName", tcoTrack->name() ); ( *it )->m_tco->saveState( dataFile, tcoElement ); tcoParent.appendChild( tcoElement ); } @@ -621,6 +624,7 @@ DataFile TrackContentObjectView::createTCODataFiles( QDomElement metadata = dataFile.createElement( "copyMetadata" ); // initialTrackIndex is the index of the track that was touched metadata.setAttribute( "initialTrackIndex", initialTrackIndex ); + metadata.setAttribute( "trackContainerId", tc->id() ); // grabbedTCOPos is the pos of the tact containing the TCO we grabbed metadata.setAttribute( "grabbedTCOPos", m_tco->startPosition() ); @@ -1316,7 +1320,7 @@ MidiTime TrackContentWidget::getPosition( int mouseX ) void TrackContentWidget::dragEnterEvent( QDragEnterEvent * dee ) { MidiTime tcoPos = MidiTime( getPosition( dee->pos().x() ).getTact(), 0 ); - if( canPasteSelection( tcoPos, dee->mimeData() ) == false ) + if( canPasteSelection( tcoPos, dee ) == false ) { dee->ignore(); } @@ -1335,8 +1339,10 @@ void TrackContentWidget::dragEnterEvent( QDragEnterEvent * dee ) * \param tcoPos the position of the TCO slot being pasted on * \param de the DropEvent generated */ -bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QMimeData * mimeData ) +bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QDropEvent* de ) { + const QMimeData * mimeData = de->mimeData(); + Track * t = getTrack(); QString type = StringPairDrag::decodeMimeKey( mimeData ); QString value = StringPairDrag::decodeMimeValue( mimeData ); @@ -1366,7 +1372,9 @@ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QMimeData * m const int currentTrackIndex = tracks.indexOf( t ); // Don't paste if we're on the same tact - if( tcoPos == grabbedTCOTact && currentTrackIndex == initialTrackIndex ) + auto sourceTrackContainerId = metadata.attributeNode( "trackContainerId" ).value().toUInt(); + if( de->source() && sourceTrackContainerId == t->trackContainer()->id() && + tcoPos == grabbedTCOTact && currentTrackIndex == initialTrackIndex ) { return false; } @@ -1389,9 +1397,9 @@ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QMimeData * m } // Track must be of the same type - Track * startTrack = tracks.at( trackIndex ); + auto startTrackType = tcoElement.attributeNode("trackType").value().toInt(); Track * endTrack = tracks.at( finalTrackIndex ); - if( startTrack->type() != endTrack->type() ) + if( startTrackType != endTrack->type() ) { return false; } @@ -1407,7 +1415,7 @@ bool TrackContentWidget::canPasteSelection( MidiTime tcoPos, const QMimeData * m */ bool TrackContentWidget::pasteSelection( MidiTime tcoPos, QDropEvent * de ) { - if( canPasteSelection( tcoPos, de->mimeData() ) == false ) + if( canPasteSelection( tcoPos, de ) == false ) { return false; } @@ -1478,7 +1486,8 @@ bool TrackContentWidget::pasteSelection( MidiTime tcoPos, QDropEvent * de ) tco->selectViewOnCreate( true ); } //check tco name, if the same as source track name dont copy - if( tco->name() == tracks[trackIndex]->name() ) + QString sourceTrackName = outerTCOElement.attributeNode( "trackName" ).value(); + if( tco->name() == sourceTrackName ) { tco->setName( "" ); }