Fix dropping clip in timeline can lead to crash if drop ended outside timeline

parent 8aa49abd
Pipeline #16298 failed with stage
in 47 seconds
...@@ -629,6 +629,7 @@ bool MyTreeView::performDrag() ...@@ -629,6 +629,7 @@ bool MyTreeView::performDrag()
drag->setPixmap(QPixmap::fromImage(image)); drag->setPixmap(QPixmap::fromImage(image));
} }
drag->exec(); drag->exec();
emit processDragEnd();
return true; return true;
} }
...@@ -1958,6 +1959,7 @@ void Bin::slotInitView(QAction *action) ...@@ -1958,6 +1959,7 @@ void Bin::slotInitView(QAction *action)
view->setSortingEnabled(true); view->setSortingEnabled(true);
view->setWordWrap(true); view->setWordWrap(true);
connect(view, &MyTreeView::updateDragMode, m_itemModel.get(), &ProjectItemModel::setDragType, Qt::DirectConnection); connect(view, &MyTreeView::updateDragMode, m_itemModel.get(), &ProjectItemModel::setDragType, Qt::DirectConnection);
connect(view, &MyTreeView::processDragEnd, this, &Bin::processDragEnd);
connect(view, &MyTreeView::displayBinFrame, this, &Bin::showBinFrame); connect(view, &MyTreeView::displayBinFrame, this, &Bin::showBinFrame);
if (!m_headerInfo.isEmpty()) { if (!m_headerInfo.isEmpty()) {
view->header()->restoreState(m_headerInfo); view->header()->restoreState(m_headerInfo);
...@@ -1994,6 +1996,7 @@ void Bin::slotInitView(QAction *action) ...@@ -1994,6 +1996,7 @@ void Bin::slotInitView(QAction *action)
view->setGridSize(QSize(zoom.width() * 1.2, zoom.width())); view->setGridSize(QSize(zoom.width() * 1.2, zoom.width()));
connect(view, &MyListView::focusView, this, &Bin::slotGotFocus); connect(view, &MyListView::focusView, this, &Bin::slotGotFocus);
connect(view, &MyListView::displayBinFrame, this, &Bin::showBinFrame); connect(view, &MyListView::displayBinFrame, this, &Bin::showBinFrame);
connect(view, &MyListView::processDragEnd, this, &Bin::processDragEnd);
} }
m_itemView->setEditTriggers(QAbstractItemView::NoEditTriggers); // DoubleClicked); m_itemView->setEditTriggers(QAbstractItemView::NoEditTriggers); // DoubleClicked);
m_itemView->setSelectionMode(QAbstractItemView::ExtendedSelection); m_itemView->setSelectionMode(QAbstractItemView::ExtendedSelection);
......
...@@ -82,6 +82,7 @@ signals: ...@@ -82,6 +82,7 @@ signals:
void focusView(); void focusView();
void updateDragMode(PlaylistState::ClipState type); void updateDragMode(PlaylistState::ClipState type);
void displayBinFrame(QModelIndex ix, int frame); void displayBinFrame(QModelIndex ix, int frame);
void processDragEnd();
private: private:
QPoint m_startPos; QPoint m_startPos;
PlaylistState::ClipState m_dragType; PlaylistState::ClipState m_dragType;
...@@ -115,6 +116,7 @@ signals: ...@@ -115,6 +116,7 @@ signals:
void focusView(); void focusView();
void updateDragMode(PlaylistState::ClipState type); void updateDragMode(PlaylistState::ClipState type);
void displayBinFrame(QModelIndex ix, int frame); void displayBinFrame(QModelIndex ix, int frame);
void processDragEnd();
}; };
class SmallJobLabel : public QPushButton class SmallJobLabel : public QPushButton
...@@ -496,6 +498,8 @@ signals: ...@@ -496,6 +498,8 @@ signals:
void refreshPanel(const QString &id); void refreshPanel(const QString &id);
/** @brief Upon selection, activate timeline target tracks. */ /** @brief Upon selection, activate timeline target tracks. */
void setupTargets(bool hasVideo, QList <int> audioStreams); void setupTargets(bool hasVideo, QList <int> audioStreams);
/** @brief A drag event ended, inform timeline. */
void processDragEnd();
}; };
#endif #endif
...@@ -2203,6 +2203,7 @@ void MainWindow::connectDocument() ...@@ -2203,6 +2203,7 @@ void MainWindow::connectDocument()
connect(m_projectMonitor, &Monitor::durationChanged, this, &MainWindow::slotUpdateProjectDuration); connect(m_projectMonitor, &Monitor::durationChanged, this, &MainWindow::slotUpdateProjectDuration);
connect(m_effectList2, &EffectListWidget::reloadFavorites, getMainTimeline(), &TimelineWidget::updateEffectFavorites); connect(m_effectList2, &EffectListWidget::reloadFavorites, getMainTimeline(), &TimelineWidget::updateEffectFavorites);
connect(m_transitionList2, &TransitionListWidget::reloadFavorites, getMainTimeline(), &TimelineWidget::updateTransitionFavorites); connect(m_transitionList2, &TransitionListWidget::reloadFavorites, getMainTimeline(), &TimelineWidget::updateTransitionFavorites);
connect(pCore->bin(), &Bin::processDragEnd, getMainTimeline(), &TimelineWidget::endDrag);
// TODO REFAC: fix // TODO REFAC: fix
// trackView->updateProfile(1.0); // trackView->updateProfile(1.0);
......
...@@ -33,6 +33,10 @@ Rectangle { ...@@ -33,6 +33,10 @@ Rectangle {
processingDrag(!root.dragInProgress) processingDrag(!root.dragInProgress)
} }
function endBinDrag() {
clipDropArea.processDrop()
}
function fitZoom() { function fitZoom() {
return scrollView.width / (timeline.duration * 1.1) return scrollView.width / (timeline.duration * 1.1)
} }
...@@ -377,8 +381,8 @@ Rectangle { ...@@ -377,8 +381,8 @@ Rectangle {
} }
} }
onExited:{ onExited:{
if (clipBeingDroppedId != -1 && drag.y < drag.x) { if (clipBeingDroppedId != -1) {
// If we exit on top, remove clip // If we exit, remove composition
controller.requestItemDeletion(clipBeingDroppedId, false) controller.requestItemDeletion(clipBeingDroppedId, false)
clearDropData() clearDropData()
} }
...@@ -394,7 +398,9 @@ Rectangle { ...@@ -394,7 +398,9 @@ Rectangle {
clearDropData() clearDropData()
} }
} }
DropArea { //Drop area for bin/clips DropArea {
//Drop area for bin/clips
id: clipDropArea
/** @brief local helper function to handle the insertion of multiple dragged items */ /** @brief local helper function to handle the insertion of multiple dragged items */
function insertAndMaybeGroup(track, frame, droppedData) { function insertAndMaybeGroup(track, frame, droppedData) {
var binIds = droppedData.split(";") var binIds = droppedData.split(";")
...@@ -424,6 +430,42 @@ Rectangle { ...@@ -424,6 +430,42 @@ Rectangle {
y: ruler.height y: ruler.height
x: headerWidth x: headerWidth
keys: 'kdenlive/producerslist' keys: 'kdenlive/producerslist'
function processDrop()
{
// Process the drop event, useful if drop event happens outside of drop area
if (clipBeingDroppedId != -1) {
var frame = controller.getClipPosition(clipBeingDroppedId)
var track = controller.getClipTrackId(clipBeingDroppedId)
if (!controller.normalEdit()) {
frame = fakeFrame
track = fakeTrack
}
/* We simulate insertion at the final position so that stored undo has correct value
* NOTE: even if dropping multiple clips, requesting the deletion of the first one is
* enough as internally it will request the group deletion
*/
controller.requestItemDeletion(clipBeingDroppedId, false)
var binIds = clipBeingDroppedData.split(";")
if (binIds.length == 1) {
if (controller.normalEdit()) {
timeline.insertClip(track, frame, clipBeingDroppedData, true, true, false)
} else {
timeline.insertClipZone(clipBeingDroppedData, track, frame)
}
} else {
if (controller.normalEdit()) {
timeline.insertClips(track, frame, binIds, true, true)
} else {
// TODO
console.log('multiple clips insert/overwrite not supported yet')
}
}
fakeTrack = -1
fakeFrame = -1
}
clearDropData()
}
onEntered: { onEntered: {
if (clipBeingMovedId == -1 && clipBeingDroppedId == -1) { if (clipBeingMovedId == -1 && clipBeingDroppedId == -1) {
//var track = Logic.getTrackIdFromPos(drag.y) //var track = Logic.getTrackIdFromPos(drag.y)
...@@ -489,38 +531,7 @@ Rectangle { ...@@ -489,38 +531,7 @@ Rectangle {
} }
} }
onDropped: { onDropped: {
if (clipBeingDroppedId != -1) { processDrop()
var frame = controller.getClipPosition(clipBeingDroppedId)
var track = controller.getClipTrackId(clipBeingDroppedId)
if (!controller.normalEdit()) {
frame = fakeFrame
track = fakeTrack
}
/* We simulate insertion at the final position so that stored undo has correct value
* NOTE: even if dropping multiple clips, requesting the deletion of the first one is
* enough as internally it will request the group deletion
*/
controller.requestItemDeletion(clipBeingDroppedId, false)
var binIds = clipBeingDroppedData.split(";")
if (binIds.length == 1) {
if (controller.normalEdit()) {
timeline.insertClip(track, frame, clipBeingDroppedData, true, true, false)
} else {
timeline.insertClipZone(clipBeingDroppedData, track, frame)
}
} else {
if (controller.normalEdit()) {
timeline.insertClips(track, frame, binIds, true, true)
} else {
// TODO
console.log('multiple clips insert/overwrite not supported yet')
}
}
fakeTrack = -1
fakeFrame = -1
}
clearDropData()
} }
} }
DropArea { //Drop area for urls (direct drop from file manager) DropArea { //Drop area for urls (direct drop from file manager)
......
...@@ -369,3 +369,9 @@ void TimelineWidget::focusTimeline() ...@@ -369,3 +369,9 @@ void TimelineWidget::focusTimeline()
} }
} }
void TimelineWidget::endDrag()
{
if (rootObject()) {
QMetaObject::invokeMethod(rootObject(), "endBinDrag");
}
}
...@@ -67,6 +67,8 @@ public slots: ...@@ -67,6 +67,8 @@ public slots:
void updateEffectFavorites(); void updateEffectFavorites();
/* @brief Favorite transitions have changed, reload model for context menu */ /* @brief Favorite transitions have changed, reload model for context menu */
void updateTransitionFavorites(); void updateTransitionFavorites();
/* @brief Bin clip drag ended, make sure we correctly processed the drop */
void endDrag();
private slots: private slots:
void slotUngrabHack(); void slotUngrabHack();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment