mirror of
https://invent.kde.org/multimedia/kdenlive
synced 2025-12-05 15:59:59 +01:00
Fixes various user-facing and non-user-facing typos. Found via: `codespell -S "*.po,*.svg,*.pgm" -L acount,afile,aline,atleast,buildin,build-in,indx,inout,nd,originaly,parth,seh,shotcut,splitted,wheight`
2043 lines
98 KiB
C++
2043 lines
98 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2020-2022 Jean-Baptiste Mardelle <jb@kdenlive.org>
|
|
SPDX-FileCopyrightText: 2021 Julius Künzel <julius.kuenzel@kde.org>
|
|
SPDX-FileCopyrightText: 2017-2019 Nicolas Carion <french.ebook.lover@gmail.com>
|
|
SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
|
*/
|
|
#include "test_utils.hpp"
|
|
// test specific headers
|
|
#include "doc/kdenlivedoc.h"
|
|
#include "timeline2/model/timelinefunctions.hpp"
|
|
|
|
using namespace fakeit;
|
|
|
|
TEST_CASE("Simple trimming operations", "[Trimming]")
|
|
{
|
|
auto binModel = pCore->projectItemModel();
|
|
binModel->clean();
|
|
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
|
|
|
|
// Here we do some trickery to enable testing.
|
|
pCore->setCurrentProfile(QStringLiteral("dv_pal"));
|
|
KdenliveDoc document(undoStack, {1, 3});
|
|
pCore->projectManager()->testSetDocument(&document);
|
|
QDateTime documentDate = QDateTime::currentDateTime();
|
|
KdenliveTests::updateTimeline(false, QString(), QString(), documentDate, 0);
|
|
auto timeline = document.getTimeline(document.uuid());
|
|
pCore->projectManager()->testSetActiveTimeline(timeline);
|
|
|
|
QString binId = KdenliveTests::createProducer(pCore->getProjectProfile(), "red", binModel);
|
|
QString binId2 = KdenliveTests::createProducer(pCore->getProjectProfile(), "blue", binModel);
|
|
QString binId3 = KdenliveTests::createProducerWithSound(pCore->getProjectProfile(), binModel);
|
|
|
|
int cid1 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
int tid1 = timeline->getTrackIndexFromPosition(3);
|
|
int tid2 = timeline->getTrackIndexFromPosition(2);
|
|
int tid3 = timeline->getTrackIndexFromPosition(1);
|
|
|
|
// Add an audio track
|
|
int tid4 = timeline->getTrackIndexFromPosition(0);
|
|
int cid2 = ClipModel::construct(timeline, binId2, -1, PlaylistState::VideoOnly);
|
|
int cid3 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
int cid4 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
int cid5 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
int cid6 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
int cid7 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
|
|
int audio1 = ClipModel::construct(timeline, binId3, -1, PlaylistState::VideoOnly);
|
|
int audio2 = ClipModel::construct(timeline, binId3, -1, PlaylistState::VideoOnly);
|
|
int audio3 = ClipModel::construct(timeline, binId3, -1, PlaylistState::VideoOnly);
|
|
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid1);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid2);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid3);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid4);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid5);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid6);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid7);
|
|
|
|
SECTION("Clip cutting")
|
|
{
|
|
// Trivial split
|
|
REQUIRE(timeline->requestClipMove(cid1, tid1, 0));
|
|
int l = timeline->getClipPlaytime(cid2);
|
|
REQUIRE(timeline->requestItemResize(cid2, l - 3, true) == l - 3);
|
|
REQUIRE(timeline->requestItemResize(cid2, l - 5, false) == l - 5);
|
|
REQUIRE(timeline->requestClipMove(cid2, tid1, l));
|
|
REQUIRE(timeline->requestClipMove(cid3, tid1, l + l - 5));
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l - 5);
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 0);
|
|
REQUIRE(timeline->getClipPosition(cid2) == l);
|
|
REQUIRE(timeline->getClipPosition(cid3) == l + l - 5);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 2);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l - 4);
|
|
};
|
|
state();
|
|
|
|
// require cut position outside the clip. Should return true and nothing is done
|
|
REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, 0));
|
|
state();
|
|
REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, 5 * l));
|
|
state();
|
|
// cut on edges doesn't do anything either
|
|
REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, l));
|
|
state();
|
|
REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, l + l - 5));
|
|
state();
|
|
|
|
REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, l + 4));
|
|
int splitted = timeline->getClipByPosition(tid1, l + 5);
|
|
auto state2 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == 4);
|
|
REQUIRE(timeline->getClipPlaytime(splitted) == l - 9);
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 0);
|
|
REQUIRE(timeline->getClipPosition(cid2) == l);
|
|
REQUIRE(timeline->getClipPosition(splitted) == l + 4);
|
|
REQUIRE(timeline->getClipPosition(cid3) == l + l - 5);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 2);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == 5);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, splitted)->getIn() == 6);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, splitted)->getOut() == l - 4);
|
|
};
|
|
state2();
|
|
|
|
undoStack->undo();
|
|
state();
|
|
|
|
undoStack->redo();
|
|
state2();
|
|
}
|
|
|
|
SECTION("Cut and resize")
|
|
{
|
|
REQUIRE(timeline->requestClipMove(cid1, tid1, 5));
|
|
int l = timeline->getClipPlaytime(cid1);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid1);
|
|
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5);
|
|
};
|
|
state();
|
|
|
|
REQUIRE(TimelineFunctions::requestClipCut(timeline, cid1, 9));
|
|
int splitted = timeline->getClipByPosition(tid1, 10);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, splitted);
|
|
auto state2 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(splitted) == tid1);
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == 4);
|
|
REQUIRE(timeline->getClipPlaytime(splitted) == l - 4);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5);
|
|
REQUIRE(timeline->getClipPosition(splitted) == 9);
|
|
};
|
|
state2();
|
|
|
|
REQUIRE(timeline->requestClipMove(splitted, tid2, 9, true, true));
|
|
REQUIRE(timeline->requestItemResize(splitted, l - 3, true, true) == -1);
|
|
REQUIRE(timeline->requestItemResize(splitted, l, false, true) == l);
|
|
REQUIRE(timeline->requestItemResize(cid1, 5, false, true) == -1);
|
|
REQUIRE(timeline->requestItemResize(cid1, l, true, true) == l);
|
|
auto state3 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(splitted) == tid2);
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l);
|
|
REQUIRE(timeline->getClipPlaytime(splitted) == l);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5);
|
|
REQUIRE(timeline->getClipPosition(splitted) == 5);
|
|
};
|
|
state3();
|
|
|
|
undoStack->undo();
|
|
undoStack->undo();
|
|
undoStack->undo();
|
|
state2();
|
|
undoStack->undo();
|
|
state();
|
|
undoStack->redo();
|
|
state2();
|
|
undoStack->redo();
|
|
undoStack->redo();
|
|
undoStack->redo();
|
|
state3();
|
|
}
|
|
|
|
SECTION("Clip cutting 2")
|
|
{
|
|
// More complex group structure split split
|
|
int l = timeline->getClipPlaytime(cid2);
|
|
REQUIRE(timeline->requestClipMove(cid1, tid1, 0));
|
|
REQUIRE(timeline->requestClipMove(cid2, tid1, l));
|
|
REQUIRE(timeline->requestClipMove(cid3, tid1, 2 * l));
|
|
REQUIRE(timeline->requestClipMove(cid4, tid2, 0));
|
|
REQUIRE(timeline->requestClipMove(cid5, tid2, l));
|
|
REQUIRE(timeline->requestClipMove(cid6, tid2, 2 * l));
|
|
REQUIRE(timeline->requestClipMove(cid7, tid1, 200));
|
|
int gid1 = timeline->requestClipsGroup(std::unordered_set<int>({cid1, cid4}), true, GroupType::Normal);
|
|
int gid2 = timeline->requestClipsGroup(std::unordered_set<int>({cid2, cid5}), true, GroupType::Normal);
|
|
int gid3 = timeline->requestClipsGroup(std::unordered_set<int>({cid3, cid6}), true, GroupType::Normal);
|
|
int gid4 = timeline->requestClipsGroup(std::unordered_set<int>({cid1, cid2, cid3, cid4, cid5, cid6, cid7}), true, GroupType::Normal);
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
int p = 0;
|
|
for (int c : std::vector<int>({cid1, cid2, cid3})) {
|
|
REQUIRE(timeline->getClipPlaytime(c) == l);
|
|
REQUIRE(timeline->getClipTrackId(c) == tid1);
|
|
REQUIRE(timeline->getClipPosition(c) == p);
|
|
p += l;
|
|
}
|
|
p = 0;
|
|
for (int c : std::vector<int>({cid4, cid5, cid6})) {
|
|
REQUIRE(timeline->getClipPlaytime(c) == l);
|
|
REQUIRE(timeline->getClipTrackId(c) == tid2);
|
|
REQUIRE(timeline->getClipPosition(c) == p);
|
|
p += l;
|
|
}
|
|
REQUIRE(timeline->getClipPosition(cid7) == 200);
|
|
REQUIRE(timeline->getClipTrackId(cid7) == tid1);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(gid1) == std::unordered_set<int>({cid1, cid4}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(gid2) == std::unordered_set<int>({cid2, cid5}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(gid3) == std::unordered_set<int>({cid3, cid6}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(gid4) == std::unordered_set<int>({gid1, gid2, gid3, cid7}));
|
|
REQUIRE(timeline->getGroupElements(cid1) == std::unordered_set<int>({cid1, cid2, cid3, cid4, cid5, cid6, cid7}));
|
|
};
|
|
state();
|
|
|
|
// These functions will return true but do nothing
|
|
REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, 0));
|
|
REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, 5 * l));
|
|
REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, l));
|
|
REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, 2 * l));
|
|
state();
|
|
|
|
REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, l + 4));
|
|
int splitted = timeline->getClipByPosition(tid1, l + 5);
|
|
int splitted2 = timeline->getClipByPosition(tid2, l + 5);
|
|
REQUIRE(splitted != splitted2);
|
|
auto check_groups = [&]() {
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(gid2) == std::unordered_set<int>({splitted, splitted2}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(gid3) == std::unordered_set<int>({cid3, cid6}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(gid4) == std::unordered_set<int>({gid2, gid3, cid7}));
|
|
REQUIRE(timeline->getGroupElements(cid3) == std::unordered_set<int>({splitted, splitted2, cid3, cid6, cid7}));
|
|
|
|
int g1b = KdenliveTests::groupUpLink(timeline)[cid1];
|
|
int g2b = KdenliveTests::groupUpLink(timeline)[cid2];
|
|
int g4b = KdenliveTests::groupsModel(timeline)->getRootId(cid1);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g1b) == std::unordered_set<int>({cid1, cid4}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g2b) == std::unordered_set<int>({cid2, cid5}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g4b) == std::unordered_set<int>({g1b, g2b}));
|
|
REQUIRE(timeline->getGroupElements(cid1) == std::unordered_set<int>({cid1, cid2, cid4, cid5}));
|
|
};
|
|
auto state2 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
int p = 0;
|
|
for (int c : std::vector<int>({cid1, cid2, cid3})) {
|
|
REQUIRE(timeline->getClipPlaytime(c) == (c == cid2 ? 4 : l));
|
|
REQUIRE(timeline->getClipTrackId(c) == tid1);
|
|
REQUIRE(timeline->getClipPosition(c) == p);
|
|
p += l;
|
|
}
|
|
p = 0;
|
|
for (int c : std::vector<int>({cid4, cid5, cid6})) {
|
|
REQUIRE(timeline->getClipPlaytime(c) == (c == cid5 ? 4 : l));
|
|
REQUIRE(timeline->getClipTrackId(c) == tid2);
|
|
REQUIRE(timeline->getClipPosition(c) == p);
|
|
p += l;
|
|
}
|
|
REQUIRE(timeline->getClipPosition(cid7) == 200);
|
|
REQUIRE(timeline->getClipTrackId(cid7) == tid1);
|
|
REQUIRE(timeline->getClipPosition(splitted) == l + 4);
|
|
REQUIRE(timeline->getClipPlaytime(splitted) == l - 4);
|
|
REQUIRE(timeline->getClipTrackId(splitted) == tid1);
|
|
REQUIRE(timeline->getClipPosition(splitted2) == l + 4);
|
|
REQUIRE(timeline->getClipPlaytime(splitted2) == l - 4);
|
|
REQUIRE(timeline->getClipTrackId(splitted2) == tid2);
|
|
check_groups();
|
|
};
|
|
state2();
|
|
|
|
REQUIRE(timeline->requestClipMove(splitted, tid1, l + 4 + 10, true, true));
|
|
REQUIRE(timeline->requestClipMove(cid1, tid2, 10, true, true));
|
|
auto state3 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
int p = 0;
|
|
for (int c : std::vector<int>({cid1, cid2, cid3})) {
|
|
REQUIRE(timeline->getClipPlaytime(c) == (c == cid2 ? 4 : l));
|
|
REQUIRE(timeline->getClipTrackId(c) == (c == cid3 ? tid1 : tid2));
|
|
REQUIRE(timeline->getClipPosition(c) == p + 10);
|
|
p += l;
|
|
}
|
|
p = 0;
|
|
for (int c : std::vector<int>({cid4, cid5, cid6})) {
|
|
REQUIRE(timeline->getClipPlaytime(c) == (c == cid5 ? 4 : l));
|
|
REQUIRE(timeline->getClipTrackId(c) == (c == cid6 ? tid2 : tid3));
|
|
REQUIRE(timeline->getClipPosition(c) == p + 10);
|
|
p += l;
|
|
}
|
|
REQUIRE(timeline->getClipPosition(cid7) == 210);
|
|
REQUIRE(timeline->getClipTrackId(cid7) == tid1);
|
|
REQUIRE(timeline->getClipPosition(splitted) == l + 4 + 10);
|
|
REQUIRE(timeline->getClipPlaytime(splitted) == l - 4);
|
|
REQUIRE(timeline->getClipTrackId(splitted) == tid1);
|
|
REQUIRE(timeline->getClipPosition(splitted2) == l + 4 + 10);
|
|
REQUIRE(timeline->getClipPlaytime(splitted2) == l - 4);
|
|
REQUIRE(timeline->getClipTrackId(splitted2) == tid2);
|
|
check_groups();
|
|
};
|
|
state3();
|
|
|
|
undoStack->undo();
|
|
undoStack->undo();
|
|
state2();
|
|
undoStack->undo();
|
|
state();
|
|
undoStack->redo();
|
|
state2();
|
|
undoStack->redo();
|
|
undoStack->redo();
|
|
state3();
|
|
}
|
|
|
|
SECTION("Simple audio split")
|
|
{
|
|
int l = timeline->getClipPlaytime(audio1);
|
|
REQUIRE(timeline->requestClipMove(audio1, tid1, 3));
|
|
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(audio1) == l);
|
|
REQUIRE(timeline->getClipPosition(audio1) == 3);
|
|
REQUIRE(timeline->getClipTrackId(audio1) == tid1);
|
|
REQUIRE(timeline->getTrackClipsCount(tid1) == 1);
|
|
REQUIRE(timeline->getTrackClipsCount(tid2) == 0);
|
|
|
|
REQUIRE(timeline->getGroupElements(audio1) == std::unordered_set<int>({audio1}));
|
|
};
|
|
state();
|
|
|
|
REQUIRE(TimelineFunctions::requestSplitAudio(timeline, audio1, {tid4}));
|
|
int splitted1 = timeline->getClipByPosition(tid4, 3);
|
|
auto state2 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(audio1) == l);
|
|
REQUIRE(timeline->getClipPosition(audio1) == 3);
|
|
REQUIRE(timeline->getClipPlaytime(splitted1) == l);
|
|
REQUIRE(timeline->getClipPosition(splitted1) == 3);
|
|
REQUIRE(timeline->getClipTrackId(audio1) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(splitted1) == tid4);
|
|
REQUIRE(timeline->getTrackClipsCount(tid1) == 1);
|
|
REQUIRE(timeline->getTrackClipsCount(tid4) == 1);
|
|
|
|
REQUIRE(timeline->getGroupElements(audio1) == std::unordered_set<int>({audio1, splitted1}));
|
|
|
|
int g1 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(audio1);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g1) == std::unordered_set<int>({audio1, splitted1}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g1) == GroupType::AVSplit);
|
|
};
|
|
state2();
|
|
|
|
undoStack->undo();
|
|
state();
|
|
undoStack->redo();
|
|
state2();
|
|
undoStack->undo();
|
|
state();
|
|
undoStack->redo();
|
|
state2();
|
|
|
|
// We also make sure that clips that are audio only cannot be further splitted
|
|
REQUIRE(timeline->requestClipMove(cid1, tid1, l + 30));
|
|
// This is a color clip, shouldn't be splittable
|
|
REQUIRE_FALSE(TimelineFunctions::requestSplitAudio(timeline, cid1, {tid2}));
|
|
// Check we cannot split audio on a video track
|
|
REQUIRE_FALSE(TimelineFunctions::requestSplitAudio(timeline, audio1, {tid2}));
|
|
}
|
|
SECTION("Split audio on a selection")
|
|
{
|
|
|
|
int l = timeline->getClipPlaytime(audio2);
|
|
REQUIRE(timeline->requestClipMove(audio1, tid1, 0));
|
|
REQUIRE(timeline->requestClipMove(audio2, tid1, l));
|
|
REQUIRE(timeline->requestClipMove(audio3, tid1, 2 * l));
|
|
|
|
std::unordered_set<int> selection{audio1, audio3, audio2};
|
|
timeline->requestSetSelection(selection);
|
|
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(audio1) == l);
|
|
REQUIRE(timeline->getClipPlaytime(audio2) == l);
|
|
REQUIRE(timeline->getClipPlaytime(audio3) == l);
|
|
REQUIRE(timeline->getClipPosition(audio1) == 0);
|
|
REQUIRE(timeline->getClipPosition(audio2) == l);
|
|
REQUIRE(timeline->getClipPosition(audio3) == l + l);
|
|
REQUIRE(timeline->getClipTrackId(audio1) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(audio2) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(audio3) == tid1);
|
|
REQUIRE(timeline->getTrackClipsCount(tid1) == 3);
|
|
REQUIRE(timeline->getTrackClipsCount(tid2) == 0);
|
|
|
|
REQUIRE(timeline->getGroupElements(audio1) == std::unordered_set<int>({audio1, audio2, audio3}));
|
|
|
|
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>({audio1, audio3, audio2}));
|
|
};
|
|
state();
|
|
|
|
REQUIRE(TimelineFunctions::requestSplitAudio(timeline, audio1, {tid4}));
|
|
int splitted1 = timeline->getClipByPosition(tid4, 0);
|
|
int splitted2 = timeline->getClipByPosition(tid4, l);
|
|
int splitted3 = timeline->getClipByPosition(tid4, 2 * l);
|
|
auto state2 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(audio1) == l);
|
|
REQUIRE(timeline->getClipPlaytime(audio2) == l);
|
|
REQUIRE(timeline->getClipPlaytime(audio3) == l);
|
|
REQUIRE(timeline->getClipPosition(audio1) == 0);
|
|
REQUIRE(timeline->getClipPosition(audio2) == l);
|
|
REQUIRE(timeline->getClipPosition(audio3) == l + l);
|
|
REQUIRE(timeline->getClipPlaytime(splitted1) == l);
|
|
REQUIRE(timeline->getClipPlaytime(splitted2) == l);
|
|
REQUIRE(timeline->getClipPlaytime(splitted3) == l);
|
|
REQUIRE(timeline->getClipPosition(splitted1) == 0);
|
|
REQUIRE(timeline->getClipPosition(splitted2) == l);
|
|
REQUIRE(timeline->getClipPosition(splitted3) == l + l);
|
|
REQUIRE(timeline->getClipTrackId(audio1) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(audio2) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(audio3) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(splitted1) == tid4);
|
|
REQUIRE(timeline->getClipTrackId(splitted2) == tid4);
|
|
REQUIRE(timeline->getClipTrackId(splitted3) == tid4);
|
|
REQUIRE(timeline->getTrackClipsCount(tid1) == 3);
|
|
REQUIRE(timeline->getTrackClipsCount(tid4) == 3);
|
|
|
|
REQUIRE(timeline->getGroupElements(audio1) == std::unordered_set<int>({audio1, splitted1, audio2, audio3, splitted2, splitted3}));
|
|
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>({audio1, splitted1, audio2, audio3, splitted2, splitted3}));
|
|
|
|
int g1 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(audio1);
|
|
int g2 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(audio2);
|
|
int g3 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(audio3);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g1) == std::unordered_set<int>({audio1, splitted1}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g2) == std::unordered_set<int>({audio2, splitted2}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g3) == std::unordered_set<int>({audio3, splitted3}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g1) == GroupType::AVSplit);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g2) == GroupType::AVSplit);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g3) == GroupType::AVSplit);
|
|
};
|
|
state2();
|
|
|
|
undoStack->undo();
|
|
state();
|
|
undoStack->redo();
|
|
state2();
|
|
}
|
|
SECTION("Cut should preserve AV groups")
|
|
{
|
|
QString binId3 = KdenliveTests::createProducerWithSound(pCore->getProjectProfile(), binModel);
|
|
|
|
int tid6 = TrackModel::construct(timeline, -1, -1, QString(), true);
|
|
int tid5 = TrackModel::construct(timeline);
|
|
|
|
// Setup timeline audio drop info
|
|
QMap<int, QString> audioInfo;
|
|
audioInfo.insert(1, QStringLiteral("stream1"));
|
|
KdenliveTests::setAudioTargets(timeline, audioInfo);
|
|
KdenliveTests::setVideoTargets(timeline, tid5);
|
|
|
|
int cid6 = -1;
|
|
int pos = 3;
|
|
REQUIRE(timeline->requestClipInsertion(binId3, tid5, pos, cid6, true, true, false));
|
|
int cid7 = KdenliveTests::groupsModel(timeline)->getSplitPartner(cid6);
|
|
int l = timeline->getClipPlaytime(cid6);
|
|
REQUIRE(l >= 10);
|
|
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getTrackClipsCount(tid5) == 1);
|
|
REQUIRE(timeline->getTrackClipsCount(tid6) == 1);
|
|
REQUIRE(timeline->getClipTrackId(cid6) == tid5);
|
|
REQUIRE(timeline->getClipTrackId(cid7) == tid6);
|
|
REQUIRE(timeline->getClipPosition(cid6) == pos);
|
|
REQUIRE(timeline->getClipPosition(cid7) == pos);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid6)->clipState() == PlaylistState::VideoOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid7)->clipState() == PlaylistState::AudioOnly);
|
|
|
|
// we check that the av group was correctly created
|
|
REQUIRE(timeline->getGroupElements(cid6) == std::unordered_set<int>({cid6, cid7}));
|
|
int g1 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(cid6);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g1) == std::unordered_set<int>({cid6, cid7}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g1) == GroupType::AVSplit);
|
|
};
|
|
state();
|
|
|
|
REQUIRE(TimelineFunctions::requestClipCut(timeline, cid6, pos + 4));
|
|
|
|
int cid8 = timeline->getClipByPosition(tid5, pos + 5);
|
|
int cid9 = timeline->getClipByPosition(tid6, pos + 5);
|
|
REQUIRE(cid8 >= 0);
|
|
REQUIRE(cid9 >= 0);
|
|
|
|
auto state2 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getTrackClipsCount(tid5) == 2);
|
|
REQUIRE(timeline->getTrackClipsCount(tid6) == 2);
|
|
REQUIRE(timeline->getClipTrackId(cid6) == tid5);
|
|
REQUIRE(timeline->getClipTrackId(cid7) == tid6);
|
|
REQUIRE(timeline->getClipTrackId(cid8) == tid5);
|
|
REQUIRE(timeline->getClipTrackId(cid9) == tid6);
|
|
|
|
REQUIRE(timeline->getClipPosition(cid6) == pos);
|
|
REQUIRE(timeline->getClipPosition(cid7) == pos);
|
|
REQUIRE(timeline->getClipPosition(cid8) == pos + 4);
|
|
REQUIRE(timeline->getClipPosition(cid9) == pos + 4);
|
|
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid6)->clipState() == PlaylistState::VideoOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid7)->clipState() == PlaylistState::AudioOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid8)->clipState() == PlaylistState::VideoOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid9)->clipState() == PlaylistState::AudioOnly);
|
|
|
|
// original AV group
|
|
REQUIRE(timeline->getGroupElements(cid6) == std::unordered_set<int>({cid6, cid7}));
|
|
int g1 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(cid6);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g1) == std::unordered_set<int>({cid6, cid7}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g1) == GroupType::AVSplit);
|
|
|
|
// new AV group
|
|
REQUIRE(timeline->getGroupElements(cid8) == std::unordered_set<int>({cid8, cid9}));
|
|
int g2 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(cid8);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g2) == std::unordered_set<int>({cid8, cid9}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g2) == GroupType::AVSplit);
|
|
};
|
|
state2();
|
|
|
|
undoStack->undo();
|
|
state();
|
|
undoStack->redo();
|
|
state2();
|
|
}
|
|
|
|
pCore->projectManager()->closeCurrentDocument(false, false);
|
|
}
|
|
|
|
TEST_CASE("Spacer operations", "[Spacer]")
|
|
{
|
|
auto binModel = pCore->projectItemModel();
|
|
binModel->clean();
|
|
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
|
|
pCore->setCurrentProfile(QStringLiteral("dv_pal"));
|
|
KdenliveDoc document(undoStack, {0, 1});
|
|
pCore->projectManager()->testSetDocument(&document);
|
|
QDateTime documentDate = QDateTime::currentDateTime();
|
|
KdenliveTests::updateTimeline(false, QString(), QString(), documentDate, 0);
|
|
auto timeline = document.getTimeline(document.uuid());
|
|
pCore->projectManager()->testSetActiveTimeline(timeline);
|
|
|
|
std::shared_ptr<MarkerListModel> guideModel = document.getGuideModel(document.uuid());
|
|
|
|
QString binId = KdenliveTests::createProducer(pCore->getProjectProfile(), "red", binModel);
|
|
QString binId2 = KdenliveTests::createProducer(pCore->getProjectProfile(), "blue", binModel);
|
|
QString binId3 = KdenliveTests::createProducerWithSound(pCore->getProjectProfile(), binModel);
|
|
|
|
int cid1 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
int tid1 = timeline->getTrackIndexFromPosition(0);
|
|
|
|
// Add an audio track
|
|
// int tid4 = TrackModel::construct(timeline, -1, -1, QString(), true);
|
|
int cid2 = ClipModel::construct(timeline, binId2, -1, PlaylistState::VideoOnly);
|
|
int cid3 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
|
|
// int audio1 = ClipModel::construct(timeline, binId3, -1, PlaylistState::VideoOnly);
|
|
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid1);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid2);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid3);
|
|
|
|
SECTION("Simple one track space insertion")
|
|
{
|
|
REQUIRE(timeline->requestClipMove(cid1, tid1, 0));
|
|
int l = timeline->getClipPlaytime(cid1);
|
|
int p2 = l + 10;
|
|
REQUIRE(timeline->requestClipMove(cid2, tid1, p2));
|
|
int p3 = l + l + 20;
|
|
REQUIRE(timeline->requestClipMove(cid3, tid1, p3));
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency(guideModel->getSnapPoints()));
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 0);
|
|
REQUIRE(timeline->getClipPosition(cid2) == p2);
|
|
REQUIRE(timeline->getClipPosition(cid3) == p3);
|
|
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l - 1);
|
|
};
|
|
state();
|
|
|
|
int spacerIid = TimelineFunctions::requestSpacerStartOperation(timeline, tid1, l + 5).first;
|
|
REQUIRE(spacerIid > -1);
|
|
std::function<bool(void)> undo = []() { return true; };
|
|
std::function<bool(void)> redo = []() { return true; };
|
|
int itemPos = timeline->getItemPosition(spacerIid);
|
|
int space = 18;
|
|
REQUIRE(TimelineFunctions::requestSpacerEndOperation(timeline, spacerIid, itemPos, itemPos + space, tid1, -1, undo, redo));
|
|
auto state1 = [&]() {
|
|
REQUIRE(timeline->checkConsistency(guideModel->getSnapPoints()));
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 0);
|
|
REQUIRE(timeline->getClipPosition(cid2) == p2 + space);
|
|
REQUIRE(timeline->getClipPosition(cid3) == p3 + space);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l - 1);
|
|
};
|
|
state1();
|
|
|
|
int startPos = timeline->getClipPosition(cid3) + l / 2;
|
|
spacerIid = TimelineFunctions::requestSpacerStartOperation(timeline, tid1, startPos).first;
|
|
REQUIRE(spacerIid > -1);
|
|
undo = []() { return true; };
|
|
redo = []() { return true; };
|
|
itemPos = timeline->getItemPosition(spacerIid);
|
|
int space2 = 3;
|
|
REQUIRE(TimelineFunctions::requestSpacerEndOperation(timeline, spacerIid, itemPos, itemPos + space2, tid1, -1, undo, redo));
|
|
auto state2 = [&]() {
|
|
REQUIRE(timeline->checkConsistency(guideModel->getSnapPoints()));
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 0);
|
|
REQUIRE(timeline->getClipPosition(cid2) == p2 + space);
|
|
REQUIRE(timeline->getClipPosition(cid3) == p3 + space + space2);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l - 1);
|
|
};
|
|
state2();
|
|
|
|
undoStack->undo();
|
|
state1();
|
|
undoStack->undo();
|
|
state();
|
|
|
|
undoStack->redo();
|
|
state1();
|
|
undoStack->redo();
|
|
state2();
|
|
}
|
|
|
|
SECTION("Simple one track space insertion with guides")
|
|
{
|
|
pCore->projectManager()->testSetActiveTimeline(timeline);
|
|
REQUIRE(timeline->requestClipMove(cid1, tid1, 0));
|
|
int l = timeline->getClipPlaytime(cid1);
|
|
int p2 = l + 10;
|
|
REQUIRE(timeline->requestClipMove(cid2, tid1, p2));
|
|
int p3 = l + l + 20;
|
|
REQUIRE(timeline->requestClipMove(cid3, tid1, p3));
|
|
double fps = pCore->getProjectProfile().fps();
|
|
guideModel->addMarker(GenTime(l / 2, fps), "guide1");
|
|
guideModel->addMarker(GenTime(l + 2, fps), "guide2");
|
|
guideModel->addMarker(GenTime(l + 7, fps), "guide3");
|
|
guideModel->addMarker(GenTime(p2 + l / 2, fps), "guide4");
|
|
guideModel->addMarker(GenTime(p3, fps), "guide5");
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency(guideModel->getSnapPoints()));
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 0);
|
|
REQUIRE(timeline->getClipPosition(cid2) == p2);
|
|
REQUIRE(timeline->getClipPosition(cid3) == p3);
|
|
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l - 1);
|
|
};
|
|
state();
|
|
|
|
int spacerIid = TimelineFunctions::requestSpacerStartOperation(timeline, tid1, l + 5).first;
|
|
REQUIRE(spacerIid > -1);
|
|
std::function<bool(void)> undo = []() { return true; };
|
|
std::function<bool(void)> redo = []() { return true; };
|
|
int itemPos = timeline->getItemPosition(spacerIid);
|
|
int space = 18;
|
|
REQUIRE(TimelineFunctions::requestSpacerEndOperation(timeline, spacerIid, itemPos, itemPos + space, tid1, l + 5, undo, redo));
|
|
auto state1 = [&]() {
|
|
REQUIRE(guideModel->getSnapPoints() == std::vector<int>{l / 2, l + 2, l + 7 + space, p2 + l / 2 + space, p3 + space});
|
|
REQUIRE(timeline->checkConsistency(guideModel->getSnapPoints()));
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 0);
|
|
REQUIRE(timeline->getClipPosition(cid2) == p2 + space);
|
|
REQUIRE(timeline->getClipPosition(cid3) == p3 + space);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l - 1);
|
|
};
|
|
state1();
|
|
|
|
int startPos = timeline->getClipPosition(cid3) + l / 2;
|
|
spacerIid = TimelineFunctions::requestSpacerStartOperation(timeline, tid1, startPos).first;
|
|
REQUIRE(spacerIid > -1);
|
|
undo = []() { return true; };
|
|
redo = []() { return true; };
|
|
itemPos = timeline->getItemPosition(spacerIid);
|
|
int space2 = 3;
|
|
REQUIRE(TimelineFunctions::requestSpacerEndOperation(timeline, spacerIid, itemPos, itemPos + space2, tid1, startPos, undo, redo));
|
|
auto state2 = [&]() {
|
|
REQUIRE(guideModel->getSnapPoints() == std::vector<int>{l / 2, l + 2, l + 7 + space, p2 + l / 2 + space, p3 + space + space2});
|
|
REQUIRE(timeline->checkConsistency(guideModel->getSnapPoints()));
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 0);
|
|
REQUIRE(timeline->getClipPosition(cid2) == p2 + space);
|
|
REQUIRE(timeline->getClipPosition(cid3) == p3 + space + space2);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l - 1);
|
|
};
|
|
state2();
|
|
|
|
undoStack->undo();
|
|
state1();
|
|
undoStack->undo();
|
|
state();
|
|
|
|
undoStack->redo();
|
|
state1();
|
|
undoStack->redo();
|
|
state2();
|
|
}
|
|
|
|
SECTION("Simple one track space deletion")
|
|
{
|
|
REQUIRE(timeline->requestClipMove(cid1, tid1, 0));
|
|
int l = timeline->getClipPlaytime(cid1);
|
|
int p2 = l + 10;
|
|
REQUIRE(timeline->requestClipMove(cid2, tid1, p2));
|
|
int p3 = l + l + 10;
|
|
REQUIRE(timeline->requestClipMove(cid3, tid1, p3));
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency(guideModel->getSnapPoints()));
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 0);
|
|
REQUIRE(timeline->getClipPosition(cid2) == p2);
|
|
REQUIRE(timeline->getClipPosition(cid3) == p3);
|
|
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l - 1);
|
|
};
|
|
state();
|
|
|
|
int spacerIid = TimelineFunctions::requestSpacerStartOperation(timeline, tid1, l + 5).first;
|
|
REQUIRE(spacerIid > -1);
|
|
std::function<bool(void)> undo = []() { return true; };
|
|
std::function<bool(void)> redo = []() { return true; };
|
|
int itemPos = timeline->getItemPosition(spacerIid);
|
|
// space to remove is larger than possible (at the end only 10 frames should be removed)
|
|
int space = 18;
|
|
REQUIRE(TimelineFunctions::requestSpacerEndOperation(timeline, spacerIid, itemPos, itemPos - space, tid1, -1, undo, redo));
|
|
auto state1 = [&]() {
|
|
REQUIRE(timeline->checkConsistency(guideModel->getSnapPoints()));
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 0);
|
|
REQUIRE(timeline->getClipPosition(cid2) == p2 - 10);
|
|
REQUIRE(timeline->getClipPosition(cid3) == p3 - 10);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l - 1);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l - 1);
|
|
};
|
|
state1();
|
|
|
|
int startPos = timeline->getClipPosition(cid3) + l / 2;
|
|
spacerIid = TimelineFunctions::requestSpacerStartOperation(timeline, tid1, startPos).first;
|
|
REQUIRE(spacerIid > -1);
|
|
undo = []() { return true; };
|
|
redo = []() { return true; };
|
|
itemPos = timeline->getItemPosition(spacerIid);
|
|
int space2 = 3;
|
|
REQUIRE(!TimelineFunctions::requestSpacerEndOperation(timeline, spacerIid, itemPos, itemPos - space2, tid1, -1, undo, redo));
|
|
state1();
|
|
|
|
undoStack->undo();
|
|
state();
|
|
|
|
undoStack->redo();
|
|
state1();
|
|
}
|
|
|
|
pCore->projectManager()->closeCurrentDocument(false, false);
|
|
}
|
|
|
|
TEST_CASE("Insert/delete", "[Trimming2]")
|
|
{
|
|
auto binModel = pCore->projectItemModel();
|
|
binModel->clean();
|
|
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
|
|
|
|
// Here we do some trickery to enable testing.
|
|
pCore->setCurrentProfile(QStringLiteral("dv_pal"));
|
|
KdenliveDoc document(undoStack);
|
|
pCore->projectManager()->testSetDocument(&document);
|
|
QDateTime documentDate = QDateTime::currentDateTime();
|
|
KdenliveTests::updateTimeline(false, QString(), QString(), documentDate, 0);
|
|
auto timeline = document.getTimeline(document.uuid());
|
|
pCore->projectManager()->testSetActiveTimeline(timeline);
|
|
|
|
QString binId = KdenliveTests::createProducerWithSound(pCore->getProjectProfile(), binModel);
|
|
int tid2 = timeline->getTrackIndexFromPosition(1);
|
|
int tid1 = timeline->getTrackIndexFromPosition(2);
|
|
|
|
// Setup timeline audio drop info
|
|
QMap<int, QString> audioInfo;
|
|
audioInfo.insert(1, QStringLiteral("stream1"));
|
|
KdenliveTests::setAudioTargets(timeline, audioInfo);
|
|
KdenliveTests::setVideoTargets(timeline, tid1);
|
|
|
|
SECTION("Remove Space should preserve groups")
|
|
{
|
|
|
|
int cid1 = -1;
|
|
REQUIRE(timeline->requestClipInsertion(binId, tid1, 3, cid1, true, true, false));
|
|
int cid2 = KdenliveTests::groupsModel(timeline)->getSplitPartner(cid1);
|
|
|
|
auto state = [&](int pos) {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getTrackClipsCount(tid1) == 1);
|
|
REQUIRE(timeline->getTrackClipsCount(tid2) == 1);
|
|
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(cid2) == tid2);
|
|
REQUIRE(timeline->getClipPosition(cid1) == pos);
|
|
REQUIRE(timeline->getClipPosition(cid2) == pos);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->clipState() == PlaylistState::VideoOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, 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 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(cid1);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g1) == std::unordered_set<int>({cid1, cid2}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g1) == GroupType::AVSplit);
|
|
};
|
|
state(3);
|
|
|
|
REQUIRE(TimelineFunctions::requestDeleteBlankAt(timeline, tid1, 1, true));
|
|
state(0);
|
|
|
|
undoStack->undo();
|
|
state(3);
|
|
undoStack->redo();
|
|
state(0);
|
|
}
|
|
|
|
SECTION("Insert zone should preserve groups")
|
|
{
|
|
int cid1 = -1;
|
|
REQUIRE(timeline->requestClipInsertion(binId, tid1, 3, cid1, true, true, false));
|
|
int cid2 = KdenliveTests::groupsModel(timeline)->getSplitPartner(cid1);
|
|
|
|
int l = timeline->getClipPlaytime(cid2);
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getTrackClipsCount(tid1) == 1);
|
|
REQUIRE(timeline->getTrackClipsCount(tid2) == 1);
|
|
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(cid2) == tid2);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 3);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 3);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->clipState() == PlaylistState::VideoOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, 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 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(cid1);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g1) == std::unordered_set<int>({cid1, cid2}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g1) == GroupType::AVSplit);
|
|
};
|
|
state();
|
|
|
|
QMap<int, int> aTarget;
|
|
aTarget.insert(tid2, 0);
|
|
KdenliveTests::setAudioTimelineTargets(timeline, aTarget);
|
|
KdenliveTests::setVideoTargets(timeline, tid1);
|
|
// Make tracks active
|
|
timeline->setTrackProperty(tid1, QStringLiteral("kdenlive:timeline_active"), QStringLiteral("1"));
|
|
timeline->setTrackProperty(tid2, QStringLiteral("kdenlive:timeline_active"), QStringLiteral("1"));
|
|
REQUIRE(TimelineFunctions::insertZone(timeline, {tid1, tid2}, binId, 3 + 2, {l / 4, 3 * l / 4}, false));
|
|
aTarget.clear();
|
|
KdenliveTests::setAudioTimelineTargets(timeline, aTarget);
|
|
KdenliveTests::setVideoTargets(timeline, -1);
|
|
int small_length = 3 * l / 4 - l / 4;
|
|
int cid3 = timeline->getClipByPosition(tid1, 3 + 2);
|
|
int cid4 = timeline->getClipByPosition(tid2, 3 + 2);
|
|
int cid5 = timeline->getClipByPosition(tid1, 3 + 2 + small_length);
|
|
int cid6 = timeline->getClipByPosition(tid2, 3 + 2 + small_length);
|
|
|
|
auto state2 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getTrackClipsCount(tid1) == 3);
|
|
REQUIRE(timeline->getTrackClipsCount(tid2) == 3);
|
|
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(cid2) == tid2);
|
|
REQUIRE(timeline->getClipTrackId(cid3) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(cid4) == tid2);
|
|
REQUIRE(timeline->getClipTrackId(cid5) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(cid6) == tid2);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 3);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 3);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 3 + 2);
|
|
REQUIRE(timeline->getClipPosition(cid4) == 3 + 2);
|
|
REQUIRE(timeline->getClipPosition(cid5) == 3 + 2 + small_length);
|
|
REQUIRE(timeline->getClipPosition(cid6) == 3 + 2 + small_length);
|
|
REQUIRE(timeline->getClipPlaytime(cid1) + timeline->getClipPlaytime(cid5) == l);
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == 2);
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == small_length);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->clipState() == PlaylistState::VideoOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->clipState() == PlaylistState::AudioOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->clipState() == PlaylistState::VideoOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid4)->clipState() == PlaylistState::AudioOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid5)->clipState() == PlaylistState::VideoOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid6)->clipState() == PlaylistState::AudioOnly);
|
|
// we check that the av group was correctly created
|
|
REQUIRE(timeline->getGroupElements(cid1) == std::unordered_set<int>({cid1, cid2}));
|
|
int g1 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(cid1);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g1) == std::unordered_set<int>({cid1, cid2}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g1) == GroupType::AVSplit);
|
|
|
|
REQUIRE(timeline->getGroupElements(cid3) == std::unordered_set<int>({cid3, cid4}));
|
|
int g2 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(cid3);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g2) == std::unordered_set<int>({cid3, cid4}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g2) == GroupType::AVSplit);
|
|
|
|
int g3 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(cid5);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g3) == std::unordered_set<int>({cid5, cid6}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g3) == GroupType::AVSplit);
|
|
};
|
|
state2();
|
|
undoStack->undo();
|
|
state();
|
|
undoStack->redo();
|
|
state2();
|
|
}
|
|
|
|
pCore->projectManager()->closeCurrentDocument(false, false);
|
|
}
|
|
|
|
TEST_CASE("Copy/paste", "[CP]")
|
|
{
|
|
auto binModel = pCore->projectItemModel();
|
|
binModel->clean();
|
|
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
|
|
|
|
pCore->setCurrentProfile(QStringLiteral("dv_pal"));
|
|
KdenliveDoc document(undoStack);
|
|
pCore->projectManager()->testSetDocument(&document);
|
|
QDateTime documentDate = QDateTime::currentDateTime();
|
|
KdenliveTests::updateTimeline(false, QString(), QString(), documentDate, 0);
|
|
auto timeline = document.getTimeline(document.uuid());
|
|
pCore->projectManager()->testSetActiveTimeline(timeline);
|
|
|
|
QString binId = KdenliveTests::createProducerWithSound(pCore->getProjectProfile(), binModel);
|
|
QString binId2 = KdenliveTests::createProducer(pCore->getProjectProfile(), "red", binModel);
|
|
|
|
int tid2b = timeline->getTrackIndexFromPosition(0);
|
|
int tid2 = timeline->getTrackIndexFromPosition(1);
|
|
int tid1 = timeline->getTrackIndexFromPosition(2);
|
|
int tid1b = timeline->getTrackIndexFromPosition(3);
|
|
|
|
// Setup timeline audio drop info
|
|
QMap<int, QString> audioInfo;
|
|
audioInfo.insert(1, QStringLiteral("stream1"));
|
|
KdenliveTests::setAudioTargets(timeline, audioInfo);
|
|
KdenliveTests::setVideoTargets(timeline, tid1);
|
|
|
|
SECTION("Simple copy paste of one clip")
|
|
{
|
|
|
|
int cid1 = -1;
|
|
REQUIRE(timeline->requestClipInsertion(binId2, tid1, 3, cid1, true, true, false));
|
|
int l = timeline->getClipPlaytime(cid1);
|
|
int cid2 = -1;
|
|
REQUIRE(timeline->requestClipInsertion(binId2, tid1, 3 + l, cid2, true, true, false));
|
|
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getTrackClipsCount(tid1) == 2);
|
|
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(cid2) == tid1);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 3);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 3 + l);
|
|
};
|
|
state();
|
|
|
|
QString cpy_str = TimelineFunctions::copyClips(timeline, {cid1});
|
|
|
|
// Try to paste in invalid positions
|
|
REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 0));
|
|
state();
|
|
REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 4));
|
|
state();
|
|
REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 4 + l));
|
|
state();
|
|
// Paste in audio track
|
|
REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid2, 0));
|
|
state();
|
|
REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid2b, 0));
|
|
state();
|
|
|
|
// Paste after the last clip
|
|
REQUIRE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 3 + 2 * l));
|
|
int cid3 = timeline->getClipByPosition(tid1, 3 + 2 * l + 1);
|
|
REQUIRE(cid3 != -1);
|
|
auto state2 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getTrackClipsCount(tid1) == 3);
|
|
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(cid2) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(cid3) == tid1);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 3);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 3 + l);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 3 + 2 * l);
|
|
};
|
|
state2();
|
|
|
|
undoStack->undo();
|
|
state();
|
|
undoStack->redo();
|
|
state2();
|
|
|
|
// Paste in different track
|
|
REQUIRE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1b, 0));
|
|
int cid4 = timeline->getClipByPosition(tid1b, 0);
|
|
REQUIRE(cid4 != -1);
|
|
auto state3 = [&]() {
|
|
state2();
|
|
REQUIRE(timeline->getTrackClipsCount(tid1b) == 1);
|
|
REQUIRE(timeline->getClipTrackId(cid4) == tid1b);
|
|
REQUIRE(timeline->getClipPosition(cid4) == 0);
|
|
};
|
|
state3();
|
|
|
|
undoStack->undo();
|
|
state2();
|
|
undoStack->undo();
|
|
state();
|
|
undoStack->redo();
|
|
state2();
|
|
undoStack->redo();
|
|
state3();
|
|
}
|
|
|
|
SECTION("Copy paste groups")
|
|
{
|
|
|
|
auto state0 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getTrackClipsCount(tid1) == 0);
|
|
REQUIRE(timeline->getTrackClipsCount(tid2) == 0);
|
|
REQUIRE(timeline->getTrackClipsCount(tid1b) == 0);
|
|
REQUIRE(timeline->getTrackClipsCount(tid2b) == 0);
|
|
};
|
|
state0();
|
|
int cid1 = -1;
|
|
REQUIRE(timeline->requestClipInsertion(binId, tid1, 3, cid1, true, true, false));
|
|
int l = timeline->getClipPlaytime(cid1);
|
|
int cid2 = KdenliveTests::groupsModel(timeline)->getSplitPartner(cid1);
|
|
|
|
auto state = [&](int count1, int count2) {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getTrackClipsCount(tid1) == count1);
|
|
REQUIRE(timeline->getTrackClipsCount(tid2) == count1);
|
|
REQUIRE(timeline->getTrackClipsCount(tid1b) == count2);
|
|
REQUIRE(timeline->getTrackClipsCount(tid2b) == count2);
|
|
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(cid2) == tid2);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 3);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 3);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->clipState() == PlaylistState::VideoOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, 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 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(cid1);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g1) == std::unordered_set<int>({cid1, cid2}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g1) == GroupType::AVSplit);
|
|
};
|
|
state(1, 0);
|
|
|
|
QString cpy_str = TimelineFunctions::copyClips(timeline, {cid1});
|
|
|
|
REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 0));
|
|
state(1, 0);
|
|
REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 4));
|
|
state(1, 0);
|
|
|
|
// potentially annoying selection
|
|
REQUIRE(timeline->requestSetSelection({cid1}));
|
|
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2});
|
|
|
|
// paste on same track, after clip
|
|
REQUIRE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 3 + 2 * l));
|
|
int cid3 = timeline->getClipByPosition(tid1, 3 + 2 * l + 1);
|
|
REQUIRE(cid3 != -1);
|
|
int cid4 = KdenliveTests::groupsModel(timeline)->getSplitPartner(cid3);
|
|
auto state2 = [&](int count1, int count2) {
|
|
state(count1, count2);
|
|
REQUIRE(timeline->getClipTrackId(cid3) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(cid4) == tid2);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 3 + 2 * l);
|
|
REQUIRE(timeline->getClipPosition(cid4) == 3 + 2 * l);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->clipState() == PlaylistState::VideoOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid4)->clipState() == PlaylistState::AudioOnly);
|
|
// we check that the av group was correctly created
|
|
REQUIRE(timeline->getGroupElements(cid3) == std::unordered_set<int>({cid3, cid4}));
|
|
int g1 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(cid3);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g1) == std::unordered_set<int>({cid3, cid4}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g1) == GroupType::AVSplit);
|
|
};
|
|
state2(2, 0);
|
|
|
|
// potentially annoying selection
|
|
REQUIRE(timeline->requestSetSelection({cid1}));
|
|
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2});
|
|
undoStack->undo();
|
|
REQUIRE(timeline->requestClearSelection());
|
|
state(1, 0);
|
|
|
|
// potentially annoying selection
|
|
REQUIRE(timeline->requestSetSelection({cid1}));
|
|
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2});
|
|
undoStack->redo();
|
|
REQUIRE(timeline->requestClearSelection());
|
|
state2(2, 0);
|
|
|
|
// another potentially annoying selection
|
|
REQUIRE(timeline->requestSetSelection({cid1, cid3}));
|
|
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3, cid4});
|
|
undoStack->undo();
|
|
REQUIRE(timeline->requestClearSelection());
|
|
state(1, 0);
|
|
REQUIRE(timeline->requestSetSelection({cid1}));
|
|
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2});
|
|
undoStack->redo();
|
|
REQUIRE(timeline->requestClearSelection());
|
|
state2(2, 0);
|
|
|
|
// now, we copy the old clips as well as those we just pasted. Let's do it using a selection
|
|
REQUIRE(timeline->requestSetSelection({cid1, cid3}));
|
|
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3, cid4});
|
|
// since everything is selected, everything should be copied here
|
|
cpy_str = TimelineFunctions::copyClips(timeline, {cid1});
|
|
|
|
REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 0));
|
|
state2(2, 0);
|
|
|
|
// parasitic selection
|
|
REQUIRE(timeline->requestSetSelection({cid1, cid3}));
|
|
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3, cid4});
|
|
|
|
// We paste on the other track
|
|
REQUIRE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1b, 0));
|
|
qDebug() << "track tid1 count" << timeline->getTrackClipsCount(tid1);
|
|
qDebug() << "track tid2 count" << timeline->getTrackClipsCount(tid2);
|
|
qDebug() << "track tid1b count" << timeline->getTrackClipsCount(tid1b);
|
|
qDebug() << "track tid2b count" << timeline->getTrackClipsCount(tid2b);
|
|
int cid5 = timeline->getClipByPosition(tid1b, 0);
|
|
REQUIRE(cid5 != -1);
|
|
int cid6 = KdenliveTests::groupsModel(timeline)->getSplitPartner(cid5);
|
|
REQUIRE(cid6 != -1);
|
|
int cid7 = timeline->getClipByPosition(tid1b, 2 * l + 1);
|
|
REQUIRE(cid7 != -1);
|
|
int cid8 = KdenliveTests::groupsModel(timeline)->getSplitPartner(cid7);
|
|
REQUIRE(cid8 != -1);
|
|
auto state3 = [&](int count1, int count2) {
|
|
state2(count1, count2);
|
|
REQUIRE(timeline->getClipTrackId(cid5) == tid1b);
|
|
REQUIRE(timeline->getClipTrackId(cid7) == tid1b);
|
|
REQUIRE(timeline->getClipTrackId(cid6) == tid2b);
|
|
REQUIRE(timeline->getClipTrackId(cid8) == tid2b);
|
|
REQUIRE(timeline->getClipPosition(cid5) == 0);
|
|
REQUIRE(timeline->getClipPosition(cid6) == 0);
|
|
REQUIRE(timeline->getClipPosition(cid7) == 2 * l);
|
|
REQUIRE(timeline->getClipPosition(cid8) == 2 * l);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid5)->clipState() == PlaylistState::VideoOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid6)->clipState() == PlaylistState::AudioOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid7)->clipState() == PlaylistState::VideoOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid8)->clipState() == PlaylistState::AudioOnly);
|
|
// we check that the av group was correctly created
|
|
REQUIRE(timeline->getGroupElements(cid5) == std::unordered_set<int>({cid5, cid6}));
|
|
int g1 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(cid5);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g1) == std::unordered_set<int>({cid5, cid6}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g1) == GroupType::AVSplit);
|
|
|
|
REQUIRE(timeline->getGroupElements(cid7) == std::unordered_set<int>({cid7, cid8}));
|
|
int g2 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(cid7);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g2) == std::unordered_set<int>({cid7, cid8}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g2) == GroupType::AVSplit);
|
|
};
|
|
state3(2, 2);
|
|
|
|
// parasitic selection
|
|
REQUIRE(timeline->requestSetSelection({cid1, cid3}));
|
|
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3, cid4});
|
|
undoStack->undo();
|
|
REQUIRE(timeline->requestClearSelection());
|
|
state2(2, 0);
|
|
REQUIRE(timeline->requestSetSelection({cid1, cid3}));
|
|
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3, cid4});
|
|
undoStack->redo();
|
|
REQUIRE(timeline->requestClearSelection());
|
|
state3(2, 2);
|
|
}
|
|
|
|
SECTION("Paste when tracks get deleted")
|
|
{
|
|
auto state0 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getTrackClipsCount(tid1) == 0);
|
|
REQUIRE(timeline->getTrackClipsCount(tid2) == 0);
|
|
REQUIRE(timeline->getTrackClipsCount(tid1b) == 0);
|
|
REQUIRE(timeline->getTrackClipsCount(tid2b) == 0);
|
|
};
|
|
state0();
|
|
int cid1 = -1;
|
|
REQUIRE(timeline->requestClipInsertion(binId, tid1, 3, cid1, true, true, false));
|
|
timeline->getClipPlaytime(cid1);
|
|
int cid2 = KdenliveTests::groupsModel(timeline)->getSplitPartner(cid1);
|
|
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getTrackClipsCount(tid1) == 1);
|
|
REQUIRE(timeline->getTrackClipsCount(tid2) == 1);
|
|
REQUIRE(timeline->getTrackClipsCount(tid1b) == 0);
|
|
REQUIRE(timeline->getTrackClipsCount(tid2b) == 0);
|
|
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(cid2) == tid2);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 3);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 3);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->clipState() == PlaylistState::VideoOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, 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 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(cid1);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g1) == std::unordered_set<int>({cid1, cid2}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g1) == GroupType::AVSplit);
|
|
};
|
|
state();
|
|
|
|
QString cpy_str = TimelineFunctions::copyClips(timeline, {cid1});
|
|
|
|
// we delete origin of the copy, paste should still be possible
|
|
REQUIRE(timeline->requestItemDeletion(cid1));
|
|
state0();
|
|
|
|
REQUIRE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 0));
|
|
int cid3 = timeline->getClipByPosition(tid1, 0);
|
|
REQUIRE(cid3 != -1);
|
|
int cid4 = KdenliveTests::groupsModel(timeline)->getSplitPartner(cid3);
|
|
auto state2 = [&](int audio) {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getTrackClipsCount(tid1) == 1);
|
|
REQUIRE(timeline->getTrackClipsCount(audio) == 1);
|
|
REQUIRE(timeline->getTrackClipsCount(tid1b) == 0);
|
|
REQUIRE(timeline->getClipTrackId(cid3) == tid1);
|
|
REQUIRE(timeline->getClipTrackId(cid4) == audio);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 0);
|
|
REQUIRE(timeline->getClipPosition(cid4) == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->clipState() == PlaylistState::VideoOnly);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid4)->clipState() == PlaylistState::AudioOnly);
|
|
// we check that the av group was correctly created
|
|
REQUIRE(timeline->getGroupElements(cid3) == std::unordered_set<int>({cid3, cid4}));
|
|
int g1 = KdenliveTests::groupsModel(timeline)->getDirectAncestor(cid3);
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getDirectChildren(g1) == std::unordered_set<int>({cid3, cid4}));
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getType(g1) == GroupType::AVSplit);
|
|
};
|
|
state2(tid2);
|
|
|
|
undoStack->undo();
|
|
state0();
|
|
undoStack->redo();
|
|
state2(tid2);
|
|
undoStack->undo();
|
|
state0();
|
|
|
|
// now, we remove all audio tracks, making paste impossible
|
|
REQUIRE(timeline->requestTrackDeletion(tid2));
|
|
REQUIRE(timeline->requestTrackDeletion(tid2b));
|
|
REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 0));
|
|
|
|
// undo one deletion
|
|
undoStack->undo();
|
|
// now, tid2b should be a valid audio track
|
|
REQUIRE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 0));
|
|
cid3 = timeline->getClipByPosition(tid1, 0);
|
|
REQUIRE(cid3 != -1);
|
|
cid4 = KdenliveTests::groupsModel(timeline)->getSplitPartner(cid3);
|
|
state2(tid2b);
|
|
}
|
|
pCore->projectManager()->closeCurrentDocument(false, false);
|
|
}
|
|
|
|
TEST_CASE("Advanced trimming operations: Slip", "[TrimmingSlip]")
|
|
{
|
|
auto binModel = pCore->projectItemModel();
|
|
binModel->clean();
|
|
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
|
|
|
|
// Here we do some trickery to enable testing.
|
|
pCore->setCurrentProfile(QStringLiteral("dv_pal"));
|
|
KdenliveDoc document(undoStack, {0, 2});
|
|
pCore->projectManager()->testSetDocument(&document);
|
|
QDateTime documentDate = QDateTime::currentDateTime();
|
|
KdenliveTests::updateTimeline(false, QString(), QString(), documentDate, 0);
|
|
auto timeline = document.getTimeline(document.uuid());
|
|
pCore->projectManager()->testSetActiveTimeline(timeline);
|
|
|
|
QString binId = KdenliveTests::createProducer(pCore->getProjectProfile(), "red", binModel);
|
|
QString binId2 = KdenliveTests::createProducer(pCore->getProjectProfile(), "blue", binModel);
|
|
|
|
int tid1 = timeline->getTrackIndexFromPosition(0);
|
|
int tid2 = timeline->getTrackIndexFromPosition(1);
|
|
|
|
int cid1 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
int cid2 = ClipModel::construct(timeline, binId2, -1, PlaylistState::VideoOnly);
|
|
int cid3 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
int cid4 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
int cid5 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid1);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid2);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid3);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid4);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid5);
|
|
|
|
// sliping a fullsized clips should not to anything
|
|
SECTION("Slip single fullsized clip")
|
|
{
|
|
REQUIRE(timeline->requestClipMove(cid1, tid1, 5));
|
|
int l = timeline->getClipPlaytime(cid1);
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l - 1);
|
|
};
|
|
state();
|
|
|
|
REQUIRE(timeline->requestClipSlip(cid1, 3) == 3);
|
|
state();
|
|
|
|
REQUIRE(timeline->requestClipSlip(cid1, -3) == -3);
|
|
state();
|
|
|
|
undoStack->undo();
|
|
state();
|
|
undoStack->undo();
|
|
state();
|
|
|
|
undoStack->redo();
|
|
state();
|
|
undoStack->redo();
|
|
state();
|
|
}
|
|
|
|
// slipping a downsized clip should only change the in and out point
|
|
SECTION("Slip single cut clip")
|
|
{
|
|
REQUIRE(timeline->requestClipMove(cid1, tid1, 5));
|
|
int l = timeline->getClipPlaytime(cid1);
|
|
REQUIRE(timeline->requestItemResize(cid1, l - 5, true) == l - 5);
|
|
REQUIRE(timeline->requestItemResize(cid1, l - 11, false) == l - 11);
|
|
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l - 11);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5 + 6);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 6);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l - 6);
|
|
};
|
|
state();
|
|
|
|
REQUIRE(timeline->requestClipSlip(cid1, 3) == 3);
|
|
auto state2 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l - 11);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5 + 6);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 3);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l - 9);
|
|
};
|
|
state2();
|
|
|
|
REQUIRE(timeline->requestClipSlip(cid1, -3) == -3);
|
|
state();
|
|
|
|
undoStack->undo();
|
|
state2();
|
|
undoStack->undo();
|
|
state();
|
|
|
|
undoStack->redo();
|
|
state2();
|
|
undoStack->redo();
|
|
state();
|
|
}
|
|
|
|
// if offset is bigger than the borders use the biggest possible offset without going beyond the borders
|
|
SECTION("Slip beyond borders")
|
|
{
|
|
REQUIRE(timeline->requestClipMove(cid1, tid1, 5));
|
|
int l = timeline->getClipPlaytime(cid1);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l);
|
|
REQUIRE(timeline->requestItemResize(cid1, l - 5, true) == l - 5);
|
|
REQUIRE(timeline->requestItemResize(cid1, l - 11, false) == l - 11);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l - 6);
|
|
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l - 11);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5 + 6);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 6);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l - 6);
|
|
};
|
|
state();
|
|
|
|
// left border
|
|
REQUIRE(timeline->requestClipSlip(cid1, 30) == 30);
|
|
auto state2 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l - 11);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5 + 6);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l - 12);
|
|
};
|
|
state2();
|
|
|
|
// right border
|
|
REQUIRE(timeline->requestClipSlip(cid1, -30) == -30);
|
|
auto state3 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l - 11);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5 + 6);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 11);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l - 1);
|
|
};
|
|
state3();
|
|
|
|
undoStack->undo();
|
|
state2();
|
|
undoStack->undo();
|
|
state();
|
|
|
|
undoStack->redo();
|
|
state2();
|
|
undoStack->redo();
|
|
state3();
|
|
}
|
|
|
|
// slipping one clip of a group should slip all members
|
|
SECTION("Slip group")
|
|
{
|
|
REQUIRE(timeline->requestClipMove(cid1, tid1, 5));
|
|
int l1 = timeline->getClipPlaytime(cid1);
|
|
REQUIRE(timeline->requestItemResize(cid1, l1 - 5, true) == l1 - 5);
|
|
REQUIRE(timeline->requestItemResize(cid1, l1 - 11, false) == l1 - 11);
|
|
|
|
REQUIRE(timeline->requestClipMove(cid2, tid1, 50));
|
|
int l2 = timeline->getClipPlaytime(cid2);
|
|
REQUIRE(timeline->requestItemResize(cid2, l2 - 11, false) == l2 - 11);
|
|
|
|
REQUIRE(timeline->requestClipMove(cid3, tid2, 25));
|
|
int l3 = timeline->getClipPlaytime(cid3);
|
|
REQUIRE(timeline->requestItemResize(cid3, l3 - 5, true) == l3 - 5);
|
|
|
|
REQUIRE(timeline->requestClipMove(cid4, tid2, 0));
|
|
int l4 = timeline->getClipPlaytime(cid4);
|
|
REQUIRE(timeline->requestItemResize(cid4, l4 - 9, true) == l4 - 9);
|
|
REQUIRE(timeline->requestItemResize(cid4, l4 - 17, false) == l4 - 17);
|
|
|
|
REQUIRE(timeline->requestClipMove(cid5, tid2, 60));
|
|
int l5 = timeline->getClipPlaytime(cid5);
|
|
int gid1 = timeline->requestClipsGroup(std::unordered_set<int>({cid1, cid2, cid3, cid4, cid5}), true, GroupType::Normal);
|
|
REQUIRE(gid1 > -1);
|
|
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l1 - 11);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5 + 6);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 6);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l1 - 6);
|
|
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 11);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 50 + 11);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 11);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l2 - 1);
|
|
REQUIRE(timeline->getClipTrackId(cid2) == tid1);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l3 - 5);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 25);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l3 - 6);
|
|
REQUIRE(timeline->getClipTrackId(cid3) == tid2);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid4) == l4 - 17);
|
|
REQUIRE(timeline->getClipPosition(cid4) == 8);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid4)->getIn() == 8);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid4)->getOut() == l4 - 10);
|
|
REQUIRE(timeline->getClipTrackId(cid4) == tid2);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid5) == l5);
|
|
REQUIRE(timeline->getClipPosition(cid5) == 60);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid5)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid5)->getOut() == l5 - 1);
|
|
REQUIRE(timeline->getClipTrackId(cid5) == tid2);
|
|
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getLeaves(gid1) == std::unordered_set<int>({cid1, cid2, cid3, cid4, cid5}));
|
|
};
|
|
state();
|
|
|
|
REQUIRE(timeline->requestClipSlip(cid1, 3) == 3);
|
|
|
|
auto state2 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l1 - 11);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5 + 6);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 3);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l1 - 9);
|
|
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 11);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 50 + 11);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 8);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l2 - 4);
|
|
REQUIRE(timeline->getClipTrackId(cid2) == tid1);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l3 - 5);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 25);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l3 - 6);
|
|
REQUIRE(timeline->getClipTrackId(cid3) == tid2);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid4) == l4 - 17);
|
|
REQUIRE(timeline->getClipPosition(cid4) == 8);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid4)->getIn() == 5);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid4)->getOut() == l4 - 13);
|
|
REQUIRE(timeline->getClipTrackId(cid4) == tid2);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid5) == l5);
|
|
REQUIRE(timeline->getClipPosition(cid5) == 60);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid5)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid5)->getOut() == l5 - 1);
|
|
REQUIRE(timeline->getClipTrackId(cid5) == tid2);
|
|
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getLeaves(gid1) == std::unordered_set<int>({cid1, cid2, cid3, cid4, cid5}));
|
|
};
|
|
state2();
|
|
|
|
REQUIRE(timeline->requestClipSlip(cid4, 30) == 30);
|
|
|
|
auto state3 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l1 - 11);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5 + 6);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l1 - 12);
|
|
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 11);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 50 + 11);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l2 - 12);
|
|
REQUIRE(timeline->getClipTrackId(cid2) == tid1);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l3 - 5);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 25);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l3 - 6);
|
|
REQUIRE(timeline->getClipTrackId(cid3) == tid2);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid4) == l4 - 17);
|
|
REQUIRE(timeline->getClipPosition(cid4) == 8);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid4)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid4)->getOut() == l4 - 18);
|
|
REQUIRE(timeline->getClipTrackId(cid4) == tid2);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid5) == l5);
|
|
REQUIRE(timeline->getClipPosition(cid5) == 60);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid5)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid5)->getOut() == l5 - 1);
|
|
REQUIRE(timeline->getClipTrackId(cid5) == tid2);
|
|
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getLeaves(gid1) == std::unordered_set<int>({cid1, cid2, cid3, cid4, cid5}));
|
|
};
|
|
state3();
|
|
|
|
undoStack->undo();
|
|
state2();
|
|
undoStack->undo();
|
|
state();
|
|
|
|
undoStack->redo();
|
|
state2();
|
|
undoStack->redo();
|
|
state3();
|
|
}
|
|
|
|
pCore->projectManager()->closeCurrentDocument(false, false);
|
|
}
|
|
|
|
TEST_CASE("Advanced trimming operations: Ripple", "[TrimmingRipple]")
|
|
{
|
|
auto binModel = pCore->projectItemModel();
|
|
binModel->clean();
|
|
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
|
|
|
|
// Here we do some trickery to enable testing.
|
|
pCore->setCurrentProfile(QStringLiteral("dv_pal"));
|
|
KdenliveDoc document(undoStack, {0, 2});
|
|
pCore->projectManager()->testSetDocument(&document);
|
|
QDateTime documentDate = QDateTime::currentDateTime();
|
|
KdenliveTests::updateTimeline(false, QString(), QString(), documentDate, 0);
|
|
auto timeline = document.getTimeline(document.uuid());
|
|
pCore->projectManager()->testSetActiveTimeline(timeline);
|
|
|
|
QString binId = KdenliveTests::createProducer(pCore->getProjectProfile(), "red", binModel);
|
|
QString binId2 = KdenliveTests::createProducer(pCore->getProjectProfile(), "blue", binModel);
|
|
|
|
int tid1 = timeline->getTrackIndexFromPosition(0);
|
|
int tid2 = timeline->getTrackIndexFromPosition(1);
|
|
|
|
int cid1 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
int cid2 = ClipModel::construct(timeline, binId2, -1, PlaylistState::VideoOnly);
|
|
int cid3 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
int cid4 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
int cid5 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
int cid6 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly);
|
|
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid1);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid2);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid3);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid4);
|
|
KdenliveTests::makeFiniteClipEnd(timeline, cid5);
|
|
|
|
// ripple resize a fullsized clip longer should not to anything
|
|
SECTION("Ripple resize single fullsized clip (longer)")
|
|
{
|
|
REQUIRE(timeline->requestClipMove(cid1, tid1, 5));
|
|
int l1 = timeline->getClipPlaytime(cid1);
|
|
|
|
REQUIRE(timeline->requestClipMove(cid2, tid1, 50));
|
|
int l2 = timeline->getClipPlaytime(cid2);
|
|
|
|
REQUIRE(timeline->requestClipMove(cid3, tid1, 80));
|
|
int l3 = timeline->getClipPlaytime(cid3);
|
|
|
|
auto state = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l1);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l1 - 1);
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l2);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 50);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l2 - 1);
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l3);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 80);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l3 - 1);
|
|
};
|
|
state();
|
|
|
|
REQUIRE(timeline->requestItemRippleResize(timeline, cid1, l1 + 5, true));
|
|
state();
|
|
|
|
REQUIRE(timeline->requestItemRippleResize(timeline, cid1, l1 + 5, false));
|
|
state();
|
|
|
|
REQUIRE(timeline->requestItemRippleResize(timeline, cid2, l2 + 5, true));
|
|
REQUIRE(timeline->requestItemRippleResize(timeline, cid1, l2 + 5, false));
|
|
state();
|
|
|
|
REQUIRE(timeline->requestItemRippleResize(timeline, cid3, l3 + 5, true));
|
|
REQUIRE(timeline->requestItemRippleResize(timeline, cid3, l3 + 5, false));
|
|
state();
|
|
|
|
undoStack->undo();
|
|
state();
|
|
undoStack->undo();
|
|
state();
|
|
|
|
undoStack->redo();
|
|
state();
|
|
undoStack->redo();
|
|
state();
|
|
}
|
|
|
|
// ripple resize a fullsized clip shorter should resize the clip and move following clips
|
|
SECTION("Ripple resize single fullsized clip (shorter)")
|
|
{
|
|
REQUIRE(timeline->requestClipMove(cid1, tid1, 5));
|
|
int l1 = timeline->getClipPlaytime(cid1);
|
|
|
|
REQUIRE(timeline->requestClipMove(cid2, tid1, 50));
|
|
int l2 = timeline->getClipPlaytime(cid2);
|
|
|
|
REQUIRE(timeline->requestClipMove(cid3, tid1, 80));
|
|
int l3 = timeline->getClipPlaytime(cid3);
|
|
|
|
auto stateA1 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l1);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l1 - 1);
|
|
};
|
|
auto stateA2 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l2);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 50);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l2 - 1);
|
|
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l3);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 80);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l3 - 1);
|
|
};
|
|
stateA1();
|
|
stateA2();
|
|
|
|
auto stateB = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 5);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 50);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l2 - 6);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l3);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 75);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l3 - 1);
|
|
};
|
|
REQUIRE(timeline->requestItemRippleResize(timeline, cid2, l2 - 5, true) == l2 - 5);
|
|
stateA1();
|
|
stateB();
|
|
|
|
auto stateC = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 8);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 50);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 3);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l2 - 6);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l3);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 72);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l3 - 1);
|
|
};
|
|
|
|
REQUIRE(timeline->requestItemRippleResize(timeline, cid2, l2 - 8, false));
|
|
stateA1();
|
|
stateC();
|
|
|
|
undoStack->undo();
|
|
stateA1();
|
|
stateB();
|
|
|
|
undoStack->undo();
|
|
stateA1();
|
|
stateA2();
|
|
|
|
undoStack->redo();
|
|
stateA1();
|
|
stateB();
|
|
|
|
undoStack->redo();
|
|
stateA1();
|
|
stateC();
|
|
}
|
|
|
|
// ripple resize a grouped clip should move the affect all group partners on other tracks with same position as well
|
|
SECTION("Ripple resize fullsized multitrack group (shorter)")
|
|
{
|
|
REQUIRE(timeline->requestClipMove(cid1, tid1, 5));
|
|
int l1 = timeline->getClipPlaytime(cid1);
|
|
|
|
REQUIRE(timeline->requestClipMove(cid2, tid1, 50));
|
|
int l2 = timeline->getClipPlaytime(cid2);
|
|
|
|
REQUIRE(timeline->requestClipMove(cid3, tid1, 80));
|
|
int l3 = timeline->getClipPlaytime(cid3);
|
|
|
|
REQUIRE(timeline->requestClipMove(cid4, tid2, 5));
|
|
int l4 = timeline->getClipPlaytime(cid4);
|
|
REQUIRE(l4 == l1);
|
|
timeline->requestClipsGroup(std::unordered_set<int>({cid1, cid4}), true, GroupType::Normal);
|
|
|
|
REQUIRE(timeline->requestClipMove(cid5, tid2, 50));
|
|
int l5 = timeline->getClipPlaytime(cid5);
|
|
REQUIRE(l5 == l2);
|
|
timeline->requestClipsGroup(std::unordered_set<int>({cid2, cid5}), true, GroupType::Normal);
|
|
|
|
REQUIRE(timeline->requestClipMove(cid6, tid2, 80));
|
|
int l6 = timeline->getClipPlaytime(cid6);
|
|
REQUIRE(l6 == l3);
|
|
timeline->requestClipsGroup(std::unordered_set<int>({cid3, cid6}), true, GroupType::Normal);
|
|
|
|
auto stateA1 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l1);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l1 - 1);
|
|
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid4) == timeline->getClipPlaytime(cid1));
|
|
REQUIRE(timeline->getClipPosition(cid4) == timeline->getClipPosition(cid1));
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid4)->getIn() == KdenliveTests::getClipPtr(timeline, cid1)->getIn());
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid4)->getOut() == KdenliveTests::getClipPtr(timeline, cid1)->getOut());
|
|
};
|
|
auto stateA2 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l2);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 50);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l2 - 1);
|
|
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l3);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 80);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l3 - 1);
|
|
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid5) == timeline->getClipPlaytime(cid2));
|
|
REQUIRE(timeline->getClipPosition(cid5) == timeline->getClipPosition(cid2));
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid5)->getIn() == KdenliveTests::getClipPtr(timeline, cid2)->getIn());
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid5)->getOut() == KdenliveTests::getClipPtr(timeline, cid2)->getOut());
|
|
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid6) == timeline->getClipPlaytime(cid3));
|
|
REQUIRE(timeline->getClipPosition(cid6) == timeline->getClipPosition(cid3));
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid6)->getIn() == KdenliveTests::getClipPtr(timeline, cid3)->getIn());
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid6)->getOut() == KdenliveTests::getClipPtr(timeline, cid3)->getOut());
|
|
};
|
|
stateA1();
|
|
stateA2();
|
|
|
|
auto stateB = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 5);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 50);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l2 - 6);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l3);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 75);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l3 - 1);
|
|
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid5) == timeline->getClipPlaytime(cid2));
|
|
REQUIRE(timeline->getClipPosition(cid5) == timeline->getClipPosition(cid2));
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid5)->getIn() == KdenliveTests::getClipPtr(timeline, cid2)->getIn());
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid5)->getOut() == KdenliveTests::getClipPtr(timeline, cid2)->getOut());
|
|
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid6) == timeline->getClipPlaytime(cid3));
|
|
REQUIRE(timeline->getClipPosition(cid6) == timeline->getClipPosition(cid3));
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid6)->getIn() == KdenliveTests::getClipPtr(timeline, cid3)->getIn());
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid6)->getOut() == KdenliveTests::getClipPtr(timeline, cid3)->getOut());
|
|
};
|
|
REQUIRE(timeline->requestItemRippleResize(timeline, cid2, l2 - 5, true) == l2 - 5);
|
|
stateA1();
|
|
stateB();
|
|
|
|
auto stateC = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 8);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 50);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 3);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l2 - 6);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l3);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 72);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l3 - 1);
|
|
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid5) == timeline->getClipPlaytime(cid2));
|
|
REQUIRE(timeline->getClipPosition(cid5) == timeline->getClipPosition(cid2));
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid5)->getIn() == KdenliveTests::getClipPtr(timeline, cid2)->getIn());
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid5)->getOut() == KdenliveTests::getClipPtr(timeline, cid2)->getOut());
|
|
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid6) == timeline->getClipPlaytime(cid3));
|
|
REQUIRE(timeline->getClipPosition(cid6) == timeline->getClipPosition(cid3));
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid6)->getIn() == KdenliveTests::getClipPtr(timeline, cid3)->getIn());
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid6)->getOut() == KdenliveTests::getClipPtr(timeline, cid3)->getOut());
|
|
};
|
|
|
|
REQUIRE(timeline->requestItemRippleResize(timeline, cid2, l2 - 8, false));
|
|
stateA1();
|
|
stateC();
|
|
|
|
undoStack->undo();
|
|
stateA1();
|
|
stateB();
|
|
|
|
undoStack->undo();
|
|
stateA1();
|
|
stateA2();
|
|
|
|
undoStack->redo();
|
|
stateA1();
|
|
stateB();
|
|
|
|
undoStack->redo();
|
|
stateA1();
|
|
stateC();
|
|
}
|
|
|
|
SECTION("Ripple resize fullsized single track group (shorter)")
|
|
{
|
|
REQUIRE(timeline->requestClipMove(cid1, tid1, 5));
|
|
int l1 = timeline->getClipPlaytime(cid1);
|
|
|
|
REQUIRE(timeline->requestClipMove(cid2, tid1, 50));
|
|
int l2 = timeline->getClipPlaytime(cid2);
|
|
|
|
REQUIRE(timeline->requestClipMove(cid3, tid1, 80));
|
|
int l3 = timeline->getClipPlaytime(cid3);
|
|
|
|
int gid1 = timeline->requestClipsGroup(std::unordered_set<int>({cid1, cid2, cid3}), true, GroupType::Normal);
|
|
|
|
auto stateA1 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid1) == l1);
|
|
REQUIRE(timeline->getClipPosition(cid1) == 5);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid1)->getOut() == l1 - 1);
|
|
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getLeaves(gid1) == std::unordered_set<int>({cid1, cid2, cid3}));
|
|
};
|
|
auto stateA2 = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l2);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 50);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l2 - 1);
|
|
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l3);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 80);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l3 - 1);
|
|
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getLeaves(gid1) == std::unordered_set<int>({cid1, cid2, cid3}));
|
|
};
|
|
stateA1();
|
|
stateA2();
|
|
|
|
auto stateB = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 5);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 50);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l2 - 6);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l3);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 75);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l3 - 1);
|
|
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getLeaves(gid1) == std::unordered_set<int>({cid1, cid2, cid3}));
|
|
};
|
|
REQUIRE(timeline->requestItemRippleResize(timeline, cid2, l2 - 5, true) == l2 - 5);
|
|
stateA1();
|
|
stateB();
|
|
|
|
auto stateC = [&]() {
|
|
REQUIRE(timeline->checkConsistency());
|
|
REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 8);
|
|
REQUIRE(timeline->getClipPosition(cid2) == 50);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getIn() == 3);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid2)->getOut() == l2 - 6);
|
|
|
|
REQUIRE(timeline->getClipPlaytime(cid3) == l3);
|
|
REQUIRE(timeline->getClipPosition(cid3) == 72);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getIn() == 0);
|
|
REQUIRE(KdenliveTests::getClipPtr(timeline, cid3)->getOut() == l3 - 1);
|
|
|
|
REQUIRE(KdenliveTests::groupsModel(timeline)->getLeaves(gid1) == std::unordered_set<int>({cid1, cid2, cid3}));
|
|
};
|
|
|
|
REQUIRE(timeline->requestItemRippleResize(timeline, cid2, l2 - 8, false));
|
|
stateA1();
|
|
stateC();
|
|
|
|
undoStack->undo();
|
|
stateA1();
|
|
stateB();
|
|
|
|
undoStack->undo();
|
|
stateA1();
|
|
stateA2();
|
|
|
|
undoStack->redo();
|
|
stateA1();
|
|
stateB();
|
|
|
|
undoStack->redo();
|
|
stateA1();
|
|
stateC();
|
|
}
|
|
|
|
pCore->projectManager()->closeCurrentDocument(false, false);
|
|
}
|