Commit 700df274 authored by Nicolas Carion's avatar Nicolas Carion
Browse files

fix issue with spacer and add test. Closes #93

parent 4a8a9ca8
Pipeline #1549 passed with stage
in 22 minutes and 1 second
......@@ -203,7 +203,7 @@ int TimelineFunctions::requestSpacerStartOperation(const std::shared_ptr<Timelin
{
std::unordered_set<int> clips = timeline->getItemsInRange(trackId, position, -1);
if (clips.size() > 0) {
timeline->requestClipsGroup(clips, false, GroupType::Selection);
timeline->requestSetSelection(clips);
return (*clips.cbegin());
}
return -1;
......@@ -220,8 +220,6 @@ bool TimelineFunctions::requestSpacerEndOperation(const std::shared_ptr<Timeline
timeline->requestCompositionMove(itemId, track, startPosition, false, false);
}
std::unordered_set<int> clips = timeline->getGroupElements(itemId);
// clear selection
timeline->requestClearSelection();
// Start undoable command
std::function<bool(void)> undo = []() { return true; };
std::function<bool(void)> redo = []() { return true; };
......@@ -239,11 +237,12 @@ bool TimelineFunctions::requestSpacerEndOperation(const std::shared_ptr<Timeline
}
}
}
if (final && clips.size() > 1) {
final = timeline->requestClipUngroup(itemId, undo, redo);
}
if (final) {
pCore->pushUndo(undo, redo, i18n("Insert space"));
if (startPosition < endPosition) {
pCore->pushUndo(undo, redo, i18n("Remove space"));
} else {
pCore->pushUndo(undo, redo, i18n("Insert space"));
}
return true;
}
return false;
......@@ -1302,3 +1301,16 @@ bool TimelineFunctions::pasteClips(const std::shared_ptr<TimelineItemModel> &tim
pCore->pushUndo(undo, redo, i18n("Paste clips"));
return true;
}
bool TimelineFunctions::requestDeleteBlankAt(const std::shared_ptr<TimelineItemModel> &timeline, int trackId, int position, bool affectAllTracks)
{
// find blank duration
int spaceDuration = timeline->getTrackById_const(trackId)->getBlankSizeAtPos(position);
int cid = requestSpacerStartOperation(timeline, affectAllTracks ? -1 : trackId, position);
if (cid == -1) {
return false;
}
int start = timeline->getItemPosition(cid);
requestSpacerEndOperation(timeline, cid, start, start - spaceDuration);
return true;
}
......@@ -70,6 +70,15 @@ struct TimelineFunctions
static bool requestMultipleClipsInsertion(const std::shared_ptr<TimelineItemModel> &timeline, const QStringList &binIds, int trackId, int position,
QList<int> &clipIds, bool logUndo, bool refreshView);
/** @brief This function will find the blank located in the given track at the given position and remove it
@returns true on success, false otherwise
@param trackId id of the track to search in
@param position of the blank
@param affectAllTracks if true, the same blank will be removed from all tracks. Note that all the tracks must have a blank at least that big in that
position
*/
static bool requestDeleteBlankAt(const std::shared_ptr<TimelineItemModel> &timeline, int trackId, int position, bool affectAllTracks);
static int requestSpacerStartOperation(const std::shared_ptr<TimelineItemModel> &timeline, int trackId, int position);
static bool requestSpacerEndOperation(const std::shared_ptr<TimelineItemModel> &timeline, int itemId, int startPosition, int endPosition);
static bool extractZone(const std::shared_ptr<TimelineItemModel> &timeline, QVector<int> tracks, QPoint zone, bool liftOnly);
......
......@@ -1221,15 +1221,10 @@ void TimelineController::removeSpace(int trackId, int frame, bool affectAllTrack
if (trackId == -1) {
trackId = m_activeTrack;
}
// find blank duration
int spaceDuration = m_model->getTrackById_const(trackId)->getBlankSizeAtPos(frame);
int cid = requestSpacerStartOperation(affectAllTracks ? -1 : trackId, frame);
if (cid == -1) {
pCore->displayMessage(i18n("No clips found to insert space"), InformationMessage, 500);
return;
bool res = TimelineFunctions::requestDeleteBlankAt(m_model, trackId, frame, affectAllTracks);
if (!res) {
pCore->displayMessage(i18n("Cannot remove space at given position"), InformationMessage, 500);
}
int start = m_model->getItemPosition(cid);
requestSpacerEndOperation(cid, start, start - spaceDuration);
}
void TimelineController::invalidateItem(int cid)
......
......@@ -520,3 +520,74 @@ TEST_CASE("Advanced trimming operations", "[Trimming]")
pCore->m_projectManager = nullptr;
Logger::print_trace();
}
TEST_CASE("Insert/delete spaces", "[Trimming2]")
{
Logger::clear();
auto binModel = pCore->projectItemModel();
binModel->clean();
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack);
// Here we do some trickery to enable testing.
// We mock the project class so that the undoStack function returns our undoStack
Mock<ProjectManager> pmMock;
When(Method(pmMock, undoStack)).AlwaysReturn(undoStack);
ProjectManager &mocked = pmMock.get();
pCore->m_projectManager = &mocked;
// We also mock timeline object to spy few functions and mock others
TimelineItemModel tim(&profile_trimming, undoStack);
Mock<TimelineItemModel> timMock(tim);
auto timeline = std::shared_ptr<TimelineItemModel>(&timMock.get(), [](...) {});
TimelineItemModel::finishConstruct(timeline, guideModel);
RESET(timMock);
QString binId = createProducerWithSound(profile_trimming, binModel);
int tid2b = TrackModel::construct(timeline, -1, -1, QString(), true);
int tid2 = TrackModel::construct(timeline, -1, -1, QString(), true);
int tid1 = TrackModel::construct(timeline);
int tid1b = TrackModel::construct(timeline);
SECTION("Remove Space should preserve groups")
{
int cid1 = -1;
REQUIRE(timeline->requestClipInsertion(binId, tid1, 3, cid1, true, true, false));
int cid2 = timeline->m_groups->getSplitPartner(cid1);
auto state = [&](int pos) {
REQUIRE(timeline->checkConsistency());
REQUIRE(timeline->getTrackClipsCount(tid1) == 1);
REQUIRE(timeline->getTrackClipsCount(tid1) == 1);
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
REQUIRE(timeline->getClipTrackId(cid2) == tid2);
REQUIRE(timeline->getClipPosition(cid1) == pos);
REQUIRE(timeline->getClipPosition(cid2) == pos);
REQUIRE(timeline->getClipPtr(cid1)->clipState() == PlaylistState::VideoOnly);
REQUIRE(timeline->getClipPtr(cid2)->clipState() == PlaylistState::AudioOnly);
// we check that the av group was correctly created
REQUIRE(timeline->getGroupElements(cid1) == std::unordered_set<int>({cid1, cid2}));
int g1 = timeline->m_groups->getDirectAncestor(cid1);
REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({cid1, cid2}));
REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit);
};
state(3);
REQUIRE(TimelineFunctions::requestDeleteBlankAt(timeline, tid1, 1, true));
state(0);
undoStack->undo();
state(3);
undoStack->redo();
state(0);
}
binModel->clean();
pCore->m_projectManager = nullptr;
Logger::print_trace();
}
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