Fix possible crash on paste clip

parent 39995d21
Pipeline #15752 passed with stage
in 14 minutes and 47 seconds
......@@ -694,7 +694,7 @@ bool ProjectItemModel::requestAddBinClip(QString &id, const QDomElement &descrip
pCore->jobManager()->startJob<AudioThumbJob>({id}, loadJob, QString());
}
if (type == ClipType::AV || type == ClipType::Video || type == ClipType::Playlist || type == ClipType::Unknown) {
pCore->jobManager()->startJob<CacheJob>({id}, thumbJob, QString());
pCore->jobManager()->startJob<CacheJob>({id}, loadJob, QString());
}
}
return res;
......
......@@ -290,6 +290,10 @@ bool AudioThumbJob::startJob()
m_dataInCache = false;
m_thumbInCache = false;
m_binClip = pCore->projectItemModel()->getClipByBinID(m_clipId);
if (m_binClip == nullptr) {
// Clip was deleted
return false;
}
if (m_binClip->audioChannels() == 0 || m_binClip->audioThumbCreated()) {
// nothing to do
m_done = true;
......
......@@ -70,6 +70,10 @@ bool CacheJob::startJob()
return false;
}
m_binClip = pCore->projectItemModel()->getClipByBinID(m_clipId);
if (m_binClip == nullptr) {
// Clip was deleted
return false;
}
if (m_binClip->clipType() != ClipType::Video && m_binClip->clipType() != ClipType::AV && m_binClip->clipType() != ClipType::Playlist) {
// Don't create thumbnail for audio clips
m_done = true;
......
......@@ -68,10 +68,18 @@ bool ThumbJob::startJob()
// We reload here, because things may have changed since creation of this job
if (m_subClip) {
auto item = pCore->projectItemModel()->getItemByBinId(m_clipId);
if (item == nullptr) {
// Clip was deleted
return false;
}
m_binClip = std::static_pointer_cast<ProjectClip>(item->parent());
m_frameNumber = item->zone().x();
} else {
m_binClip = pCore->projectItemModel()->getClipByBinID(m_clipId);
if (m_binClip == nullptr) {
// Clip was deleted
return false;
}
if (m_frameNumber < 0) {
m_frameNumber = qMax(0, m_binClip->getProducerIntProperty(QStringLiteral("kdenlive:thumbnailFrame")));
}
......
......@@ -1435,6 +1435,8 @@ bool TimelineFunctions::pasteClips(const std::shared_ptr<TimelineItemModel> &tim
}
int offset = copiedItems.documentElement().attribute(QStringLiteral("offset")).toInt();
std::function<bool(void)> timeline_undo = []() { return true; };
std::function<bool(void)> timeline_redo = []() { return true; };
bool res = true;
QLocale locale;
std::unordered_map<int, int> correspondingIds;
......@@ -1462,7 +1464,7 @@ bool TimelineFunctions::pasteClips(const std::shared_ptr<TimelineItemModel> &tim
warp_pitch = prod.attribute(QStringLiteral("warp_pitch")).toInt();
}
int newId;
bool created = timeline->requestClipCreation(originalId, newId, timeline->getTrackById_const(curTrackId)->trackType(), speed, warp_pitch, undo, redo);
bool created = timeline->requestClipCreation(originalId, newId, timeline->getTrackById_const(curTrackId)->trackType(), speed, warp_pitch, timeline_undo, timeline_redo);
if (created) {
// Master producer is ready
// ids.removeAll(originalId);
......@@ -1481,11 +1483,11 @@ bool TimelineFunctions::pasteClips(const std::shared_ptr<TimelineItemModel> &tim
timeline->m_allClips[newId]->setInOut(in, out);
int targetId = prod.attribute(QStringLiteral("id")).toInt();
correspondingIds[targetId] = newId;
res = res && timeline->getTrackById(curTrackId)->requestClipInsertion(newId, position + pos, true, true, undo, redo);
res = res && timeline->getTrackById(curTrackId)->requestClipInsertion(newId, position + pos, true, true, timeline_undo, timeline_redo);
// paste effects
if (res) {
std::shared_ptr<EffectStackModel> destStack = timeline->getClipEffectStackModel(newId);
destStack->fromXml(prod.firstChildElement(QStringLiteral("effects")), undo, redo);
destStack->fromXml(prod.firstChildElement(QStringLiteral("effects")), timeline_undo, timeline_redo);
} else {
break;
}
......@@ -1511,18 +1513,19 @@ bool TimelineFunctions::pasteClips(const std::shared_ptr<TimelineItemModel> &tim
transProps->set(props.at(j).toElement().attribute(QStringLiteral("name")).toUtf8().constData(),
props.at(j).toElement().text().toUtf8().constData());
}
res = res && timeline->requestCompositionInsertion(originalId, curTrackId, aTrackId, position + pos, out - in + 1, std::move(transProps), newId, undo, redo);
res = res && timeline->requestCompositionInsertion(originalId, curTrackId, aTrackId, position + pos, out - in + 1, std::move(transProps), newId, timeline_undo, timeline_redo);
}
}
if (!res) {
undo();
timeline_undo();
pCore->pushUndo(undo, redo, i18n("Paste clips"));
pCore->displayMessage(i18n("Could not paste items in timeline"), InformationMessage, 500);
return false;
}
// Rebuild groups
const QString groupsData = copiedItems.documentElement().firstChildElement(QStringLiteral("groups")).text();
if (!groupsData.isEmpty()) {
timeline->m_groups->fromJsonWithOffset(groupsData, tracksMap, position - offset, undo, redo);
timeline->m_groups->fromJsonWithOffset(groupsData, tracksMap, position - offset, timeline_undo, timeline_redo);
}
// unsure to clear selection in undo/redo too.
Fun unselect = [&]() {
......@@ -1531,8 +1534,9 @@ bool TimelineFunctions::pasteClips(const std::shared_ptr<TimelineItemModel> &tim
qDebug() << "after Selection " << timeline->m_currentSelection;
return true;
};
PUSH_FRONT_LAMBDA(unselect, undo);
PUSH_FRONT_LAMBDA(unselect, redo);
PUSH_FRONT_LAMBDA(unselect, timeline_undo);
PUSH_FRONT_LAMBDA(unselect, timeline_redo);
UPDATE_UNDO_REDO_NOLOCK(timeline_redo, timeline_undo, undo, redo);
pCore->pushUndo(undo, redo, i18n("Paste clips"));
return true;
}
......
......@@ -182,7 +182,6 @@ Fun TrackModel::requestClipInsertion_lambda(int clipId, int position, bool updat
m_playlists[0].unlock();
if (finalMove && !groupMove) {
ptr->updateDuration();
}
return index != -1 && end_function(0);
}
......
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