Fix some bugs and crashes in group management

parent 252b0feb
......@@ -936,8 +936,12 @@ bool ProjectClip::selfSoftDelete(Fun &undo, Fun &redo)
{
auto toDelete = m_registeredClips; // we cannot use m_registeredClips directly, because it will be modified during loop
for (const auto &clip : toDelete) {
if (m_registeredClips.count(clip.first) == 0) {
// clip already deleted, was probably grouped with another one
continue;
}
if (auto timeline = clip.second.lock()) {
timeline->requestClipDeletion(clip.first, undo, redo);
timeline->requestItemDeletion(clip.first, undo, redo);
} else {
qDebug() << "Error while deleting clip: timeline unavailable";
Q_ASSERT(false);
......
......@@ -208,7 +208,7 @@ bool TimelineFunctions::liftZone(std::shared_ptr<TimelineItemModel> timeline, in
}
std::unordered_set<int> clips = timeline->getItemsAfterPosition(trackId, zone.x(), zone.y() - 1);
for (const auto &clipId : clips) {
timeline->requestClipDeletion(clipId, undo, redo);
timeline->requestItemDeletion(clipId, undo, redo);
}
return true;
}
......
......@@ -83,7 +83,6 @@ TimelineModel::TimelineModel(Mlt::Profile *profile, std::weak_ptr<DocUndoStack>
TimelineModel::~TimelineModel()
{
// Remove black background
std::vector<int> all_ids;
for (auto tracks : m_iteratorTable) {
all_ids.push_back(tracks.first);
......@@ -525,6 +524,15 @@ bool TimelineModel::requestClipInsertion(const QString &binClipId, int trackId,
return true;
}
bool TimelineModel::requestItemDeletion(int clipId, Fun &undo, Fun &redo)
{
QWriteLocker locker(&m_lock);
if (m_groups->isInGroup(clipId)) {
return requestGroupDeletion(clipId, undo, redo);
}
return requestClipDeletion(clipId, undo, redo);
}
bool TimelineModel::requestItemDeletion(int itemId, bool logUndo)
{
#ifdef LOGGING
......@@ -692,12 +700,24 @@ bool TimelineModel::requestGroupDeletion(int clipId, bool logUndo)
QWriteLocker locker(&m_lock);
Fun undo = []() { return true; };
Fun redo = []() { return true; };
bool res = requestGroupDeletion(clipId, undo, redo);
if (res && logUndo) {
PUSH_UNDO(undo, redo, i18n("Remove group"));
}
return res;
}
bool TimelineModel::requestGroupDeletion(int clipId, Fun &undo, Fun &redo)
{
// we do a breadth first exploration of the group tree, ungroup (delete) every inner node, and then delete all the leaves.
std::queue<int> group_queue;
group_queue.push(m_groups->getRootId(clipId));
std::unordered_set<int> all_clips;
while (!group_queue.empty()) {
int current_group = group_queue.front();
if (m_temporarySelectionGroup == current_group) {
m_temporarySelectionGroup = -1;
}
group_queue.pop();
Q_ASSERT(isGroup(current_group));
auto children = m_groups->getDirectChildren(current_group);
......@@ -727,12 +747,6 @@ bool TimelineModel::requestGroupDeletion(int clipId, bool logUndo)
return false;
}
}
if (m_temporarySelectionGroup == clipId) {
m_temporarySelectionGroup = -1;
}
if (logUndo) {
PUSH_UNDO(undo, redo, i18n("Remove group"));
}
return true;
}
......@@ -824,7 +838,8 @@ int TimelineModel::requestClipsGroup(const std::unordered_set<int> &ids, bool lo
Fun undo = []() { return true; };
Fun redo = []() { return true; };
if (m_temporarySelectionGroup > -1) {
requestClipUngroup(m_temporarySelectionGroup, undo, redo);
int firstChild = *m_groups->getDirectChildren(m_temporarySelectionGroup).begin();
requestClipUngroup(firstChild, undo, redo);
m_temporarySelectionGroup = -1;
}
int result = requestClipsGroup(ids, undo, redo, type);
......
......@@ -320,9 +320,8 @@ public:
requestGroupDeletion @param clipId is the ID of the clip/composition
@param logUndo if set to false, no undo object is stored */
Q_INVOKABLE bool requestItemDeletion(int clipId, bool logUndo = true);
/* Same function, but accumulates undo and redo, and doesn't check for group*/
bool requestClipDeletion(int clipId, Fun &undo, Fun &redo);
bool requestCompositionDeletion(int compositionId, Fun &undo, Fun &redo);
/* Same function, but accumulates undo and redo*/
bool requestItemDeletion(int clipId, Fun &undo, Fun &redo);
/* @brief Move a group to a specific position
This action is undoable
......@@ -345,6 +344,7 @@ public:
@param clipId is the id of the clip that triggers the group deletion
*/
Q_INVOKABLE bool requestGroupDeletion(int clipId, bool logUndo = true);
bool requestGroupDeletion(int clipId, Fun &undo, Fun &redo);
/* @brief Change the duration of an item (clip or composition)
This action is undoable
......@@ -558,6 +558,10 @@ protected:
/* @brief Unplant the composition with given Id */
bool unplantComposition(int compoId);
/* Same function, but accumulates undo and redo, and doesn't check for group*/
bool requestClipDeletion(int clipId, Fun &undo, Fun &redo);
bool requestCompositionDeletion(int compositionId, Fun &undo, Fun &redo);
public:
/* @brief Debugging function that checks consistency with Mlt objects */
bool checkConsistency();
......
......@@ -230,7 +230,7 @@ Rectangle {
startX = parent.x
root.stopScrolling = true
clipRoot.forceActiveFocus();
if (mouse.button == Qt.LeftButton || !clipRoot.selected) {
if (!clipRoot.selected) {
clipRoot.clicked(clipRoot, mouse.modifiers == Qt.ShiftModifier)
}
drag.target = clipRoot
......
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