1 #include "doc/kdenlivedoc.h" 2 #include "test_utils.hpp" 3 4 using namespace fakeit; 5 Mlt::Profile profile_trimming; 6 7 TEST_CASE("Simple trimming operations", "[Trimming]") 8 { 9 auto binModel = pCore->projectItemModel(); 10 binModel->clean(); 11 std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr); 12 std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack); 13 14 // Here we do some trickery to enable testing. 15 // We mock the project class so that the undoStack function returns our undoStack 16 17 Mock<ProjectManager> pmMock; 18 When(Method(pmMock, undoStack)).AlwaysReturn(undoStack); 19 When(Method(pmMock, cacheDir)).AlwaysReturn(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))); 20 21 ProjectManager &mocked = pmMock.get(); 22 pCore->m_projectManager = &mocked; 23 24 // We also mock timeline object to spy few functions and mock others 25 TimelineItemModel tim(&profile_trimming, undoStack); 26 Mock<TimelineItemModel> timMock(tim); __anonf52080220102(...) 27 auto timeline = std::shared_ptr<TimelineItemModel>(&timMock.get(), [](...) {}); 28 TimelineItemModel::finishConstruct(timeline, guideModel); 29 30 RESET(timMock) 31 32 QString binId = createProducer(profile_trimming, "red", binModel); 33 QString binId2 = createProducer(profile_trimming, "blue", binModel); 34 QString binId3 = createProducerWithSound(profile_trimming, binModel); 35 36 int cid1 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 37 int tid1 = TrackModel::construct(timeline); 38 int tid2 = TrackModel::construct(timeline); 39 int tid3 = TrackModel::construct(timeline); 40 41 // Add an audio track 42 int tid4 = TrackModel::construct(timeline, -1, -1, QString(), true); 43 int cid2 = ClipModel::construct(timeline, binId2, -1, PlaylistState::VideoOnly); 44 int cid3 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 45 int cid4 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 46 int cid5 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 47 int cid6 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 48 int cid7 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 49 50 int audio1 = ClipModel::construct(timeline, binId3, -1, PlaylistState::VideoOnly); 51 int audio2 = ClipModel::construct(timeline, binId3, -1, PlaylistState::VideoOnly); 52 int audio3 = ClipModel::construct(timeline, binId3, -1, PlaylistState::VideoOnly); 53 54 timeline->m_allClips[cid1]->m_endlessResize = false; 55 timeline->m_allClips[cid2]->m_endlessResize = false; 56 timeline->m_allClips[cid3]->m_endlessResize = false; 57 timeline->m_allClips[cid4]->m_endlessResize = false; 58 timeline->m_allClips[cid5]->m_endlessResize = false; 59 timeline->m_allClips[cid6]->m_endlessResize = false; 60 timeline->m_allClips[cid7]->m_endlessResize = false; 61 62 SECTION("Clip cutting") 63 { 64 // Trivial split 65 REQUIRE(timeline->requestClipMove(cid1, tid1, 0)); 66 int l = timeline->getClipPlaytime(cid2); 67 REQUIRE(timeline->requestItemResize(cid2, l - 3, true) == l - 3); 68 REQUIRE(timeline->requestItemResize(cid2, l - 5, false) == l - 5); 69 REQUIRE(timeline->requestClipMove(cid2, tid1, l)); 70 REQUIRE(timeline->requestClipMove(cid3, tid1, l + l - 5)); __anonf52080220202() 71 auto state = [&]() { 72 REQUIRE(timeline->checkConsistency()); 73 REQUIRE(timeline->getClipPlaytime(cid1) == l); 74 REQUIRE(timeline->getClipPlaytime(cid2) == l - 5); 75 REQUIRE(timeline->getClipPlaytime(cid3) == l); 76 REQUIRE(timeline->getClipPosition(cid1) == 0); 77 REQUIRE(timeline->getClipPosition(cid2) == l); 78 REQUIRE(timeline->getClipPosition(cid3) == l + l - 5); 79 REQUIRE(timeline->getClipPtr(cid2)->getIn() == 2); 80 REQUIRE(timeline->getClipPtr(cid2)->getOut() == l - 4); 81 }; 82 state(); 83 84 // require cut position outside the clip. Should return true and nothing is done 85 REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, 0)); 86 state(); 87 REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, 5 * l)); 88 state(); 89 // cut on edges doesn't do anything either 90 REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, l)); 91 state(); 92 REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, l + l - 5)); 93 state(); 94 95 REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, l + 4)); 96 int splitted = timeline->getClipByPosition(tid1, l + 5); __anonf52080220302() 97 auto state2 = [&]() { 98 REQUIRE(timeline->checkConsistency()); 99 REQUIRE(timeline->getClipPlaytime(cid1) == l); 100 REQUIRE(timeline->getClipPlaytime(cid2) == 4); 101 REQUIRE(timeline->getClipPlaytime(splitted) == l - 9); 102 REQUIRE(timeline->getClipPlaytime(cid3) == l); 103 REQUIRE(timeline->getClipPosition(cid1) == 0); 104 REQUIRE(timeline->getClipPosition(cid2) == l); 105 REQUIRE(timeline->getClipPosition(splitted) == l + 4); 106 REQUIRE(timeline->getClipPosition(cid3) == l + l - 5); 107 REQUIRE(timeline->getClipPtr(cid2)->getIn() == 2); 108 REQUIRE(timeline->getClipPtr(cid2)->getOut() == 5); 109 REQUIRE(timeline->getClipPtr(splitted)->getIn() == 6); 110 REQUIRE(timeline->getClipPtr(splitted)->getOut() == l - 4); 111 }; 112 state2(); 113 114 undoStack->undo(); 115 state(); 116 117 undoStack->redo(); 118 state2(); 119 } 120 121 SECTION("Cut and resize") 122 { 123 REQUIRE(timeline->requestClipMove(cid1, tid1, 5)); 124 int l = timeline->getClipPlaytime(cid1); 125 timeline->m_allClips[cid1]->m_endlessResize = false; 126 __anonf52080220402() 127 auto state = [&]() { 128 REQUIRE(timeline->checkConsistency()); 129 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 130 REQUIRE(timeline->getClipPlaytime(cid1) == l); 131 REQUIRE(timeline->getClipPosition(cid1) == 5); 132 }; 133 state(); 134 135 REQUIRE(TimelineFunctions::requestClipCut(timeline, cid1, 9)); 136 int splitted = timeline->getClipByPosition(tid1, 10); 137 timeline->m_allClips[splitted]->m_endlessResize = false; __anonf52080220502() 138 auto state2 = [&]() { 139 REQUIRE(timeline->checkConsistency()); 140 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 141 REQUIRE(timeline->getClipTrackId(splitted) == tid1); 142 REQUIRE(timeline->getClipPlaytime(cid1) == 4); 143 REQUIRE(timeline->getClipPlaytime(splitted) == l - 4); 144 REQUIRE(timeline->getClipPosition(cid1) == 5); 145 REQUIRE(timeline->getClipPosition(splitted) == 9); 146 }; 147 state2(); 148 149 REQUIRE(timeline->requestClipMove(splitted, tid2, 9, true, true)); 150 REQUIRE(timeline->requestItemResize(splitted, l - 3, true, true) == -1); 151 REQUIRE(timeline->requestItemResize(splitted, l, false, true) == l); 152 REQUIRE(timeline->requestItemResize(cid1, 5, false, true) == -1); 153 REQUIRE(timeline->requestItemResize(cid1, l, true, true) == l); __anonf52080220602() 154 auto state3 = [&]() { 155 REQUIRE(timeline->checkConsistency()); 156 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 157 REQUIRE(timeline->getClipTrackId(splitted) == tid2); 158 REQUIRE(timeline->getClipPlaytime(cid1) == l); 159 REQUIRE(timeline->getClipPlaytime(splitted) == l); 160 REQUIRE(timeline->getClipPosition(cid1) == 5); 161 REQUIRE(timeline->getClipPosition(splitted) == 5); 162 }; 163 state3(); 164 165 undoStack->undo(); 166 undoStack->undo(); 167 undoStack->undo(); 168 state2(); 169 undoStack->undo(); 170 state(); 171 undoStack->redo(); 172 state2(); 173 undoStack->redo(); 174 undoStack->redo(); 175 undoStack->redo(); 176 state3(); 177 } 178 179 SECTION("Clip cutting 2") 180 { 181 // More complex group structure split split 182 int l = timeline->getClipPlaytime(cid2); 183 REQUIRE(timeline->requestClipMove(cid1, tid1, 0)); 184 REQUIRE(timeline->requestClipMove(cid2, tid1, l)); 185 REQUIRE(timeline->requestClipMove(cid3, tid1, 2 * l)); 186 REQUIRE(timeline->requestClipMove(cid4, tid2, 0)); 187 REQUIRE(timeline->requestClipMove(cid5, tid2, l)); 188 REQUIRE(timeline->requestClipMove(cid6, tid2, 2 * l)); 189 REQUIRE(timeline->requestClipMove(cid7, tid1, 200)); 190 int gid1 = timeline->requestClipsGroup(std::unordered_set<int>({cid1, cid4}), true, GroupType::Normal); 191 int gid2 = timeline->requestClipsGroup(std::unordered_set<int>({cid2, cid5}), true, GroupType::Normal); 192 int gid3 = timeline->requestClipsGroup(std::unordered_set<int>({cid3, cid6}), true, GroupType::Normal); 193 int gid4 = timeline->requestClipsGroup(std::unordered_set<int>({cid1, cid2, cid3, cid4, cid5, cid6, cid7}), true, GroupType::Normal); __anonf52080220702() 194 auto state = [&]() { 195 REQUIRE(timeline->checkConsistency()); 196 int p = 0; 197 for (int c : std::vector<int>({cid1, cid2, cid3})) { 198 REQUIRE(timeline->getClipPlaytime(c) == l); 199 REQUIRE(timeline->getClipTrackId(c) == tid1); 200 REQUIRE(timeline->getClipPosition(c) == p); 201 p += l; 202 } 203 p = 0; 204 for (int c : std::vector<int>({cid4, cid5, cid6})) { 205 REQUIRE(timeline->getClipPlaytime(c) == l); 206 REQUIRE(timeline->getClipTrackId(c) == tid2); 207 REQUIRE(timeline->getClipPosition(c) == p); 208 p += l; 209 } 210 REQUIRE(timeline->getClipPosition(cid7) == 200); 211 REQUIRE(timeline->getClipTrackId(cid7) == tid1); 212 REQUIRE(timeline->m_groups->getDirectChildren(gid1) == std::unordered_set<int>({cid1, cid4})); 213 REQUIRE(timeline->m_groups->getDirectChildren(gid2) == std::unordered_set<int>({cid2, cid5})); 214 REQUIRE(timeline->m_groups->getDirectChildren(gid3) == std::unordered_set<int>({cid3, cid6})); 215 REQUIRE(timeline->m_groups->getDirectChildren(gid4) == std::unordered_set<int>({gid1, gid2, gid3, cid7})); 216 REQUIRE(timeline->getGroupElements(cid1) == std::unordered_set<int>({cid1, cid2, cid3, cid4, cid5, cid6, cid7})); 217 }; 218 state(); 219 220 // These functions will return true but do nothing 221 REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, 0)); 222 REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, 5 * l)); 223 REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, l)); 224 REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, 2 * l)); 225 state(); 226 227 REQUIRE(TimelineFunctions::requestClipCut(timeline, cid2, l + 4)); 228 int splitted = timeline->getClipByPosition(tid1, l + 5); 229 int splitted2 = timeline->getClipByPosition(tid2, l + 5); 230 REQUIRE(splitted != splitted2); __anonf52080220802() 231 auto check_groups = [&]() { 232 REQUIRE(timeline->m_groups->getDirectChildren(gid2) == std::unordered_set<int>({splitted, splitted2})); 233 REQUIRE(timeline->m_groups->getDirectChildren(gid3) == std::unordered_set<int>({cid3, cid6})); 234 REQUIRE(timeline->m_groups->getDirectChildren(gid4) == std::unordered_set<int>({gid2, gid3, cid7})); 235 REQUIRE(timeline->getGroupElements(cid3) == std::unordered_set<int>({splitted, splitted2, cid3, cid6, cid7})); 236 237 int g1b = timeline->m_groups->m_upLink[cid1]; 238 int g2b = timeline->m_groups->m_upLink[cid2]; 239 int g4b = timeline->m_groups->getRootId(cid1); 240 REQUIRE(timeline->m_groups->getDirectChildren(g1b) == std::unordered_set<int>({cid1, cid4})); 241 REQUIRE(timeline->m_groups->getDirectChildren(g2b) == std::unordered_set<int>({cid2, cid5})); 242 REQUIRE(timeline->m_groups->getDirectChildren(g4b) == std::unordered_set<int>({g1b, g2b})); 243 REQUIRE(timeline->getGroupElements(cid1) == std::unordered_set<int>({cid1, cid2, cid4, cid5})); 244 }; __anonf52080220902() 245 auto state2 = [&]() { 246 REQUIRE(timeline->checkConsistency()); 247 int p = 0; 248 for (int c : std::vector<int>({cid1, cid2, cid3})) { 249 REQUIRE(timeline->getClipPlaytime(c) == (c == cid2 ? 4 : l)); 250 REQUIRE(timeline->getClipTrackId(c) == tid1); 251 REQUIRE(timeline->getClipPosition(c) == p); 252 p += l; 253 } 254 p = 0; 255 for (int c : std::vector<int>({cid4, cid5, cid6})) { 256 REQUIRE(timeline->getClipPlaytime(c) == (c == cid5 ? 4 : l)); 257 REQUIRE(timeline->getClipTrackId(c) == tid2); 258 REQUIRE(timeline->getClipPosition(c) == p); 259 p += l; 260 } 261 REQUIRE(timeline->getClipPosition(cid7) == 200); 262 REQUIRE(timeline->getClipTrackId(cid7) == tid1); 263 REQUIRE(timeline->getClipPosition(splitted) == l + 4); 264 REQUIRE(timeline->getClipPlaytime(splitted) == l - 4); 265 REQUIRE(timeline->getClipTrackId(splitted) == tid1); 266 REQUIRE(timeline->getClipPosition(splitted2) == l + 4); 267 REQUIRE(timeline->getClipPlaytime(splitted2) == l - 4); 268 REQUIRE(timeline->getClipTrackId(splitted2) == tid2); 269 check_groups(); 270 }; 271 state2(); 272 273 REQUIRE(timeline->requestClipMove(splitted, tid1, l + 4 + 10, true, true)); 274 REQUIRE(timeline->requestClipMove(cid1, tid2, 10, true, true)); __anonf52080220a02() 275 auto state3 = [&]() { 276 REQUIRE(timeline->checkConsistency()); 277 int p = 0; 278 for (int c : std::vector<int>({cid1, cid2, cid3})) { 279 REQUIRE(timeline->getClipPlaytime(c) == (c == cid2 ? 4 : l)); 280 REQUIRE(timeline->getClipTrackId(c) == (c == cid3 ? tid1 : tid2)); 281 REQUIRE(timeline->getClipPosition(c) == p + 10); 282 p += l; 283 } 284 p = 0; 285 for (int c : std::vector<int>({cid4, cid5, cid6})) { 286 REQUIRE(timeline->getClipPlaytime(c) == (c == cid5 ? 4 : l)); 287 REQUIRE(timeline->getClipTrackId(c) == (c == cid6 ? tid2 : tid3)); 288 REQUIRE(timeline->getClipPosition(c) == p + 10); 289 p += l; 290 } 291 REQUIRE(timeline->getClipPosition(cid7) == 210); 292 REQUIRE(timeline->getClipTrackId(cid7) == tid1); 293 REQUIRE(timeline->getClipPosition(splitted) == l + 4 + 10); 294 REQUIRE(timeline->getClipPlaytime(splitted) == l - 4); 295 REQUIRE(timeline->getClipTrackId(splitted) == tid1); 296 REQUIRE(timeline->getClipPosition(splitted2) == l + 4 + 10); 297 REQUIRE(timeline->getClipPlaytime(splitted2) == l - 4); 298 REQUIRE(timeline->getClipTrackId(splitted2) == tid2); 299 check_groups(); 300 }; 301 state3(); 302 303 undoStack->undo(); 304 undoStack->undo(); 305 state2(); 306 undoStack->undo(); 307 state(); 308 undoStack->redo(); 309 state2(); 310 undoStack->redo(); 311 undoStack->redo(); 312 state3(); 313 } 314 315 SECTION("Simple audio split") 316 { 317 int l = timeline->getClipPlaytime(audio1); 318 REQUIRE(timeline->requestClipMove(audio1, tid1, 3)); 319 __anonf52080220b02() 320 auto state = [&]() { 321 REQUIRE(timeline->checkConsistency()); 322 REQUIRE(timeline->getClipPlaytime(audio1) == l); 323 REQUIRE(timeline->getClipPosition(audio1) == 3); 324 REQUIRE(timeline->getClipTrackId(audio1) == tid1); 325 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 326 REQUIRE(timeline->getTrackClipsCount(tid2) == 0); 327 328 REQUIRE(timeline->getGroupElements(audio1) == std::unordered_set<int>({audio1})); 329 }; 330 state(); 331 332 REQUIRE(TimelineFunctions::requestSplitAudio(timeline, audio1, tid4)); 333 int splitted1 = timeline->getClipByPosition(tid4, 3); __anonf52080220c02() 334 auto state2 = [&]() { 335 REQUIRE(timeline->checkConsistency()); 336 REQUIRE(timeline->getClipPlaytime(audio1) == l); 337 REQUIRE(timeline->getClipPosition(audio1) == 3); 338 REQUIRE(timeline->getClipPlaytime(splitted1) == l); 339 REQUIRE(timeline->getClipPosition(splitted1) == 3); 340 REQUIRE(timeline->getClipTrackId(audio1) == tid1); 341 REQUIRE(timeline->getClipTrackId(splitted1) == tid4); 342 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 343 REQUIRE(timeline->getTrackClipsCount(tid4) == 1); 344 345 REQUIRE(timeline->getGroupElements(audio1) == std::unordered_set<int>({audio1, splitted1})); 346 347 int g1 = timeline->m_groups->getDirectAncestor(audio1); 348 REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({audio1, splitted1})); 349 REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit); 350 }; 351 state2(); 352 353 undoStack->undo(); 354 state(); 355 undoStack->redo(); 356 state2(); 357 undoStack->undo(); 358 state(); 359 undoStack->redo(); 360 state2(); 361 362 // We also make sure that clips that are audio only cannot be further splitted 363 REQUIRE(timeline->requestClipMove(cid1, tid1, l + 30)); 364 // This is a color clip, shouldn't be splittable 365 REQUIRE_FALSE(TimelineFunctions::requestSplitAudio(timeline, cid1, tid2)); 366 // Check we cannot split audio on a video track 367 REQUIRE_FALSE(TimelineFunctions::requestSplitAudio(timeline, audio1, tid2)); 368 } 369 SECTION("Split audio on a selection") 370 { 371 372 int l = timeline->getClipPlaytime(audio2); 373 REQUIRE(timeline->requestClipMove(audio1, tid1, 0)); 374 REQUIRE(timeline->requestClipMove(audio2, tid1, l)); 375 REQUIRE(timeline->requestClipMove(audio3, tid1, 2 * l)); 376 377 std::unordered_set<int> selection{audio1, audio3, audio2}; 378 timeline->requestSetSelection(selection); 379 __anonf52080220d02() 380 auto state = [&]() { 381 REQUIRE(timeline->checkConsistency()); 382 REQUIRE(timeline->getClipPlaytime(audio1) == l); 383 REQUIRE(timeline->getClipPlaytime(audio2) == l); 384 REQUIRE(timeline->getClipPlaytime(audio3) == l); 385 REQUIRE(timeline->getClipPosition(audio1) == 0); 386 REQUIRE(timeline->getClipPosition(audio2) == l); 387 REQUIRE(timeline->getClipPosition(audio3) == l + l); 388 REQUIRE(timeline->getClipTrackId(audio1) == tid1); 389 REQUIRE(timeline->getClipTrackId(audio2) == tid1); 390 REQUIRE(timeline->getClipTrackId(audio3) == tid1); 391 REQUIRE(timeline->getTrackClipsCount(tid1) == 3); 392 REQUIRE(timeline->getTrackClipsCount(tid2) == 0); 393 394 REQUIRE(timeline->getGroupElements(audio1) == std::unordered_set<int>({audio1, audio2, audio3})); 395 396 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>({audio1, audio3, audio2})); 397 }; 398 state(); 399 400 REQUIRE(TimelineFunctions::requestSplitAudio(timeline, audio1, tid4)); 401 int splitted1 = timeline->getClipByPosition(tid4, 0); 402 int splitted2 = timeline->getClipByPosition(tid4, l); 403 int splitted3 = timeline->getClipByPosition(tid4, 2 * l); __anonf52080220e02() 404 auto state2 = [&]() { 405 REQUIRE(timeline->checkConsistency()); 406 REQUIRE(timeline->getClipPlaytime(audio1) == l); 407 REQUIRE(timeline->getClipPlaytime(audio2) == l); 408 REQUIRE(timeline->getClipPlaytime(audio3) == l); 409 REQUIRE(timeline->getClipPosition(audio1) == 0); 410 REQUIRE(timeline->getClipPosition(audio2) == l); 411 REQUIRE(timeline->getClipPosition(audio3) == l + l); 412 REQUIRE(timeline->getClipPlaytime(splitted1) == l); 413 REQUIRE(timeline->getClipPlaytime(splitted2) == l); 414 REQUIRE(timeline->getClipPlaytime(splitted3) == l); 415 REQUIRE(timeline->getClipPosition(splitted1) == 0); 416 REQUIRE(timeline->getClipPosition(splitted2) == l); 417 REQUIRE(timeline->getClipPosition(splitted3) == l + l); 418 REQUIRE(timeline->getClipTrackId(audio1) == tid1); 419 REQUIRE(timeline->getClipTrackId(audio2) == tid1); 420 REQUIRE(timeline->getClipTrackId(audio3) == tid1); 421 REQUIRE(timeline->getClipTrackId(splitted1) == tid4); 422 REQUIRE(timeline->getClipTrackId(splitted2) == tid4); 423 REQUIRE(timeline->getClipTrackId(splitted3) == tid4); 424 REQUIRE(timeline->getTrackClipsCount(tid1) == 3); 425 REQUIRE(timeline->getTrackClipsCount(tid4) == 3); 426 427 REQUIRE(timeline->getGroupElements(audio1) == std::unordered_set<int>({audio1, splitted1, audio2, audio3, splitted2, splitted3})); 428 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>({audio1, splitted1, audio2, audio3, splitted2, splitted3})); 429 430 int g1 = timeline->m_groups->getDirectAncestor(audio1); 431 int g2 = timeline->m_groups->getDirectAncestor(audio2); 432 int g3 = timeline->m_groups->getDirectAncestor(audio3); 433 REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({audio1, splitted1})); 434 REQUIRE(timeline->m_groups->getDirectChildren(g2) == std::unordered_set<int>({audio2, splitted2})); 435 REQUIRE(timeline->m_groups->getDirectChildren(g3) == std::unordered_set<int>({audio3, splitted3})); 436 REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit); 437 REQUIRE(timeline->m_groups->getType(g2) == GroupType::AVSplit); 438 REQUIRE(timeline->m_groups->getType(g3) == GroupType::AVSplit); 439 }; 440 state2(); 441 442 undoStack->undo(); 443 state(); 444 undoStack->redo(); 445 state2(); 446 } 447 SECTION("Cut should preserve AV groups") 448 { 449 QString binId3 = createProducerWithSound(profile_trimming, binModel); 450 451 int tid6 = TrackModel::construct(timeline, -1, -1, QString(), true); 452 int tid5 = TrackModel::construct(timeline); 453 454 // Setup timeline audio drop info 455 QMap <int, QString>audioInfo; 456 audioInfo.insert(1,QStringLiteral("stream1")); 457 timeline->m_binAudioTargets = audioInfo; 458 timeline->m_videoTarget = tid5; 459 460 int cid6 = -1; 461 int pos = 3; 462 REQUIRE(timeline->requestClipInsertion(binId3, tid5, pos, cid6, true, true, false)); 463 int cid7 = timeline->m_groups->getSplitPartner(cid6); 464 int l = timeline->getClipPlaytime(cid6); 465 REQUIRE(l >= 10); 466 __anonf52080220f02() 467 auto state = [&]() { 468 REQUIRE(timeline->checkConsistency()); 469 REQUIRE(timeline->getTrackClipsCount(tid5) == 1); 470 REQUIRE(timeline->getTrackClipsCount(tid6) == 1); 471 REQUIRE(timeline->getClipTrackId(cid6) == tid5); 472 REQUIRE(timeline->getClipTrackId(cid7) == tid6); 473 REQUIRE(timeline->getClipPosition(cid6) == pos); 474 REQUIRE(timeline->getClipPosition(cid7) == pos); 475 REQUIRE(timeline->getClipPtr(cid6)->clipState() == PlaylistState::VideoOnly); 476 REQUIRE(timeline->getClipPtr(cid7)->clipState() == PlaylistState::AudioOnly); 477 478 // we check that the av group was correctly created 479 REQUIRE(timeline->getGroupElements(cid6) == std::unordered_set<int>({cid6, cid7})); 480 int g1 = timeline->m_groups->getDirectAncestor(cid6); 481 REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({cid6, cid7})); 482 REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit); 483 }; 484 state(); 485 486 REQUIRE(TimelineFunctions::requestClipCut(timeline, cid6, pos + 4)); 487 488 int cid8 = timeline->getClipByPosition(tid5, pos + 5); 489 int cid9 = timeline->getClipByPosition(tid6, pos + 5); 490 REQUIRE(cid8 >= 0); 491 REQUIRE(cid9 >= 0); 492 __anonf52080221002() 493 auto state2 = [&]() { 494 REQUIRE(timeline->checkConsistency()); 495 REQUIRE(timeline->getTrackClipsCount(tid5) == 2); 496 REQUIRE(timeline->getTrackClipsCount(tid6) == 2); 497 REQUIRE(timeline->getClipTrackId(cid6) == tid5); 498 REQUIRE(timeline->getClipTrackId(cid7) == tid6); 499 REQUIRE(timeline->getClipTrackId(cid8) == tid5); 500 REQUIRE(timeline->getClipTrackId(cid9) == tid6); 501 502 REQUIRE(timeline->getClipPosition(cid6) == pos); 503 REQUIRE(timeline->getClipPosition(cid7) == pos); 504 REQUIRE(timeline->getClipPosition(cid8) == pos + 4); 505 REQUIRE(timeline->getClipPosition(cid9) == pos + 4); 506 507 REQUIRE(timeline->getClipPtr(cid6)->clipState() == PlaylistState::VideoOnly); 508 REQUIRE(timeline->getClipPtr(cid7)->clipState() == PlaylistState::AudioOnly); 509 REQUIRE(timeline->getClipPtr(cid8)->clipState() == PlaylistState::VideoOnly); 510 REQUIRE(timeline->getClipPtr(cid9)->clipState() == PlaylistState::AudioOnly); 511 512 // original AV group 513 REQUIRE(timeline->getGroupElements(cid6) == std::unordered_set<int>({cid6, cid7})); 514 int g1 = timeline->m_groups->getDirectAncestor(cid6); 515 REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({cid6, cid7})); 516 REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit); 517 518 // new AV group 519 REQUIRE(timeline->getGroupElements(cid8) == std::unordered_set<int>({cid8, cid9})); 520 int g2 = timeline->m_groups->getDirectAncestor(cid8); 521 REQUIRE(timeline->m_groups->getDirectChildren(g2) == std::unordered_set<int>({cid8, cid9})); 522 REQUIRE(timeline->m_groups->getType(g2) == GroupType::AVSplit); 523 }; 524 state2(); 525 526 undoStack->undo(); 527 state(); 528 undoStack->redo(); 529 state2(); 530 } 531 532 binModel->clean(); 533 pCore->m_projectManager = nullptr; 534 } 535 536 TEST_CASE("Insert/delete", "[Trimming2]") 537 { 538 auto binModel = pCore->projectItemModel(); 539 binModel->clean(); 540 std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr); 541 std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack); 542 543 // Here we do some trickery to enable testing. 544 // We mock the project class so that the undoStack function returns our undoStack 545 546 Mock<ProjectManager> pmMock; 547 When(Method(pmMock, undoStack)).AlwaysReturn(undoStack); 548 When(Method(pmMock, cacheDir)).AlwaysReturn(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))); 549 When(Method(pmMock, getGuideModel)).AlwaysReturn(guideModel); 550 551 ProjectManager &mocked = pmMock.get(); 552 pCore->m_projectManager = &mocked; 553 554 // We also mock timeline object to spy few functions and mock others 555 TimelineItemModel tim(&profile_trimming, undoStack); 556 Mock<TimelineItemModel> timMock(tim); __anonf52080221102(...) 557 auto timeline = std::shared_ptr<TimelineItemModel>(&timMock.get(), [](...) {}); 558 TimelineItemModel::finishConstruct(timeline, guideModel); 559 560 RESET(timMock); 561 562 QString binId = createProducerWithSound(profile_trimming, binModel); 563 564 TrackModel::construct(timeline, -1, -1, QString(), true); 565 int tid2 = TrackModel::construct(timeline, -1, -1, QString(), true); 566 int tid1 = TrackModel::construct(timeline); 567 TrackModel::construct(timeline); 568 569 // Setup timeline audio drop info 570 QMap <int, QString>audioInfo; 571 audioInfo.insert(1,QStringLiteral("stream1")); 572 timeline->m_binAudioTargets = audioInfo; 573 timeline->m_videoTarget = tid1; 574 575 SECTION("Remove Space should preserve groups") 576 { 577 578 int cid1 = -1; 579 REQUIRE(timeline->requestClipInsertion(binId, tid1, 3, cid1, true, true, false)); 580 int cid2 = timeline->m_groups->getSplitPartner(cid1); 581 __anonf52080221202(int pos) 582 auto state = [&](int pos) { 583 REQUIRE(timeline->checkConsistency()); 584 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 585 REQUIRE(timeline->getTrackClipsCount(tid2) == 1); 586 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 587 REQUIRE(timeline->getClipTrackId(cid2) == tid2); 588 REQUIRE(timeline->getClipPosition(cid1) == pos); 589 REQUIRE(timeline->getClipPosition(cid2) == pos); 590 REQUIRE(timeline->getClipPtr(cid1)->clipState() == PlaylistState::VideoOnly); 591 REQUIRE(timeline->getClipPtr(cid2)->clipState() == PlaylistState::AudioOnly); 592 // we check that the av group was correctly created 593 REQUIRE(timeline->getGroupElements(cid1) == std::unordered_set<int>({cid1, cid2})); 594 int g1 = timeline->m_groups->getDirectAncestor(cid1); 595 REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({cid1, cid2})); 596 REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit); 597 }; 598 state(3); 599 600 REQUIRE(TimelineFunctions::requestDeleteBlankAt(timeline, tid1, 1, true)); 601 state(0); 602 603 undoStack->undo(); 604 state(3); 605 undoStack->redo(); 606 state(0); 607 } 608 609 SECTION("Insert zone should preserve groups") 610 { 611 int cid1 = -1; 612 REQUIRE(timeline->requestClipInsertion(binId, tid1, 3, cid1, true, true, false)); 613 int cid2 = timeline->m_groups->getSplitPartner(cid1); 614 615 int l = timeline->getClipPlaytime(cid2); __anonf52080221302() 616 auto state = [&]() { 617 REQUIRE(timeline->checkConsistency()); 618 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 619 REQUIRE(timeline->getTrackClipsCount(tid2) == 1); 620 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 621 REQUIRE(timeline->getClipTrackId(cid2) == tid2); 622 REQUIRE(timeline->getClipPosition(cid1) == 3); 623 REQUIRE(timeline->getClipPosition(cid2) == 3); 624 REQUIRE(timeline->getClipPtr(cid1)->clipState() == PlaylistState::VideoOnly); 625 REQUIRE(timeline->getClipPtr(cid2)->clipState() == PlaylistState::AudioOnly); 626 // we check that the av group was correctly created 627 REQUIRE(timeline->getGroupElements(cid1) == std::unordered_set<int>({cid1, cid2})); 628 int g1 = timeline->m_groups->getDirectAncestor(cid1); 629 REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({cid1, cid2})); 630 REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit); 631 }; 632 state(); 633 634 timeline->m_audioTarget.insert(tid2, 0); 635 timeline->m_videoTarget = tid1; 636 // Make tracks active 637 timeline->setTrackProperty(tid1, QStringLiteral("kdenlive:timeline_active"), QStringLiteral("1")); 638 timeline->setTrackProperty(tid2, QStringLiteral("kdenlive:timeline_active"), QStringLiteral("1")); 639 REQUIRE(TimelineFunctions::insertZone(timeline, {tid1, tid2}, binId, 3 + 2, {l / 4, 3 * l / 4}, false)); 640 timeline->m_audioTarget.clear(); 641 timeline->m_videoTarget = -1; 642 int small_length = 3 * l / 4 - l / 4; 643 int cid3 = timeline->getClipByPosition(tid1, 3 + 2); 644 int cid4 = timeline->getClipByPosition(tid2, 3 + 2); 645 int cid5 = timeline->getClipByPosition(tid1, 3 + 2 + small_length); 646 int cid6 = timeline->getClipByPosition(tid2, 3 + 2 + small_length); 647 __anonf52080221402() 648 auto state2 = [&]() { 649 REQUIRE(timeline->checkConsistency()); 650 REQUIRE(timeline->getTrackClipsCount(tid1) == 3); 651 REQUIRE(timeline->getTrackClipsCount(tid2) == 3); 652 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 653 REQUIRE(timeline->getClipTrackId(cid2) == tid2); 654 REQUIRE(timeline->getClipTrackId(cid3) == tid1); 655 REQUIRE(timeline->getClipTrackId(cid4) == tid2); 656 REQUIRE(timeline->getClipTrackId(cid5) == tid1); 657 REQUIRE(timeline->getClipTrackId(cid6) == tid2); 658 REQUIRE(timeline->getClipPosition(cid1) == 3); 659 REQUIRE(timeline->getClipPosition(cid2) == 3); 660 REQUIRE(timeline->getClipPosition(cid3) == 3 + 2); 661 REQUIRE(timeline->getClipPosition(cid4) == 3 + 2); 662 REQUIRE(timeline->getClipPosition(cid5) == 3 + 2 + small_length); 663 REQUIRE(timeline->getClipPosition(cid6) == 3 + 2 + small_length); 664 REQUIRE(timeline->getClipPlaytime(cid1) + timeline->getClipPlaytime(cid5) == l); 665 REQUIRE(timeline->getClipPlaytime(cid1) == 2); 666 REQUIRE(timeline->getClipPlaytime(cid3) == small_length); 667 REQUIRE(timeline->getClipPtr(cid1)->clipState() == PlaylistState::VideoOnly); 668 REQUIRE(timeline->getClipPtr(cid2)->clipState() == PlaylistState::AudioOnly); 669 REQUIRE(timeline->getClipPtr(cid3)->clipState() == PlaylistState::VideoOnly); 670 REQUIRE(timeline->getClipPtr(cid4)->clipState() == PlaylistState::AudioOnly); 671 REQUIRE(timeline->getClipPtr(cid5)->clipState() == PlaylistState::VideoOnly); 672 REQUIRE(timeline->getClipPtr(cid6)->clipState() == PlaylistState::AudioOnly); 673 // we check that the av group was correctly created 674 REQUIRE(timeline->getGroupElements(cid1) == std::unordered_set<int>({cid1, cid2})); 675 int g1 = timeline->m_groups->getDirectAncestor(cid1); 676 REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({cid1, cid2})); 677 REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit); 678 679 REQUIRE(timeline->getGroupElements(cid3) == std::unordered_set<int>({cid3, cid4})); 680 int g2 = timeline->m_groups->getDirectAncestor(cid3); 681 REQUIRE(timeline->m_groups->getDirectChildren(g2) == std::unordered_set<int>({cid3, cid4})); 682 REQUIRE(timeline->m_groups->getType(g2) == GroupType::AVSplit); 683 684 int g3 = timeline->m_groups->getDirectAncestor(cid5); 685 REQUIRE(timeline->m_groups->getDirectChildren(g3) == std::unordered_set<int>({cid5, cid6})); 686 REQUIRE(timeline->m_groups->getType(g3) == GroupType::AVSplit); 687 }; 688 state2(); 689 undoStack->undo(); 690 state(); 691 undoStack->redo(); 692 state2(); 693 } 694 695 binModel->clean(); 696 pCore->m_projectManager = nullptr; 697 } 698 699 TEST_CASE("Copy/paste", "[CP]") 700 { 701 auto binModel = pCore->projectItemModel(); 702 binModel->clean(); 703 std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr); 704 std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack); 705 706 // Here we do some trickery to enable testing. 707 708 // we mock a doc to stub the getDocumentProperty 709 710 Mock<KdenliveDoc> docMock; __anonf52080221502(const QString &name, const QString &defaultValue) 711 When(Method(docMock, getDocumentProperty)).AlwaysDo([](const QString &name, const QString &defaultValue) { 712 Q_UNUSED(name) Q_UNUSED(defaultValue) 713 qDebug() << "Intercepted call"; 714 return QStringLiteral("dummyId"); 715 }); 716 717 KdenliveDoc &mockedDoc = docMock.get(); 718 719 // We mock the project class so that the undoStack function returns our undoStack, and our mocked document 720 Mock<ProjectManager> pmMock; 721 When(Method(pmMock, undoStack)).AlwaysReturn(undoStack); 722 When(Method(pmMock, cacheDir)).AlwaysReturn(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))); 723 When(Method(pmMock, current)).AlwaysReturn(&mockedDoc); 724 725 ProjectManager &mocked = pmMock.get(); 726 pCore->m_projectManager = &mocked; 727 728 // We also mock timeline object to spy few functions and mock others 729 TimelineItemModel tim(&profile_trimming, undoStack); 730 Mock<TimelineItemModel> timMock(tim); __anonf52080221602(...) 731 auto timeline = std::shared_ptr<TimelineItemModel>(&timMock.get(), [](...) {}); 732 TimelineItemModel::finishConstruct(timeline, guideModel); 733 734 RESET(timMock) 735 736 QString binId = createProducerWithSound(profile_trimming, binModel); 737 QString binId2 = createProducer(profile_trimming, "red", binModel); 738 739 int tid2b = TrackModel::construct(timeline, -1, -1, QString(), true); 740 int tid2 = TrackModel::construct(timeline, -1, -1, QString(), true); 741 int tid1 = TrackModel::construct(timeline); 742 int tid1b = TrackModel::construct(timeline); 743 744 // Setup timeline audio drop info 745 QMap <int, QString>audioInfo; 746 audioInfo.insert(1,QStringLiteral("stream1")); 747 timeline->m_binAudioTargets = audioInfo; 748 timeline->m_videoTarget = tid1; 749 750 SECTION("Simple copy paste of one clip") 751 { 752 753 int cid1 = -1; 754 REQUIRE(timeline->requestClipInsertion(binId2, tid1, 3, cid1, true, true, false)); 755 int l = timeline->getClipPlaytime(cid1); 756 int cid2 = -1; 757 REQUIRE(timeline->requestClipInsertion(binId2, tid1, 3 + l, cid2, true, true, false)); 758 __anonf52080221702() 759 auto state = [&]() { 760 REQUIRE(timeline->checkConsistency()); 761 REQUIRE(timeline->getTrackClipsCount(tid1) == 2); 762 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 763 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 764 REQUIRE(timeline->getClipPosition(cid1) == 3); 765 REQUIRE(timeline->getClipPosition(cid2) == 3 + l); 766 }; 767 state(); 768 769 QString cpy_str = TimelineFunctions::copyClips(timeline, {cid1}); 770 771 // Try to paste in invalid positions 772 REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 0)); 773 state(); 774 REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 4)); 775 state(); 776 REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 4 + l)); 777 state(); 778 // Paste in audio track 779 REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid2, 0)); 780 state(); 781 REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid2b, 0)); 782 state(); 783 784 // Paste after the last clip 785 REQUIRE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 3 + 2 * l)); 786 int cid3 = timeline->getTrackById(tid1)->getClipByPosition(3 + 2 * l + 1); 787 REQUIRE(cid3 != -1); __anonf52080221802() 788 auto state2 = [&]() { 789 REQUIRE(timeline->checkConsistency()); 790 REQUIRE(timeline->getTrackClipsCount(tid1) == 3); 791 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 792 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 793 REQUIRE(timeline->getClipTrackId(cid3) == tid1); 794 REQUIRE(timeline->getClipPosition(cid1) == 3); 795 REQUIRE(timeline->getClipPosition(cid2) == 3 + l); 796 REQUIRE(timeline->getClipPosition(cid3) == 3 + 2 * l); 797 }; 798 state2(); 799 800 undoStack->undo(); 801 state(); 802 undoStack->redo(); 803 state2(); 804 805 // Paste in different track 806 REQUIRE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1b, 0)); 807 int cid4 = timeline->getTrackById(tid1b)->getClipByPosition(0); 808 REQUIRE(cid4 != -1); __anonf52080221902() 809 auto state3 = [&]() { 810 state2(); 811 REQUIRE(timeline->getTrackClipsCount(tid1b) == 1); 812 REQUIRE(timeline->getClipTrackId(cid4) == tid1b); 813 REQUIRE(timeline->getClipPosition(cid4) == 0); 814 }; 815 state3(); 816 817 undoStack->undo(); 818 state2(); 819 undoStack->undo(); 820 state(); 821 undoStack->redo(); 822 state2(); 823 undoStack->redo(); 824 state3(); 825 } 826 827 SECTION("Copy paste groups") 828 { 829 __anonf52080221a02() 830 auto state0 = [&]() { 831 REQUIRE(timeline->checkConsistency()); 832 REQUIRE(timeline->getTrackClipsCount(tid1) == 0); 833 REQUIRE(timeline->getTrackClipsCount(tid2) == 0); 834 REQUIRE(timeline->getTrackClipsCount(tid1b) == 0); 835 REQUIRE(timeline->getTrackClipsCount(tid2b) == 0); 836 }; 837 state0(); 838 int cid1 = -1; 839 REQUIRE(timeline->requestClipInsertion(binId, tid1, 3, cid1, true, true, false)); 840 int l = timeline->getClipPlaytime(cid1); 841 int cid2 = timeline->m_groups->getSplitPartner(cid1); 842 __anonf52080221b02(int count1, int count2) 843 auto state = [&](int count1, int count2) { 844 REQUIRE(timeline->checkConsistency()); 845 REQUIRE(timeline->getTrackClipsCount(tid1) == count1); 846 REQUIRE(timeline->getTrackClipsCount(tid2) == count1); 847 REQUIRE(timeline->getTrackClipsCount(tid1b) == count2); 848 REQUIRE(timeline->getTrackClipsCount(tid2b) == count2); 849 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 850 REQUIRE(timeline->getClipTrackId(cid2) == tid2); 851 REQUIRE(timeline->getClipPosition(cid1) == 3); 852 REQUIRE(timeline->getClipPosition(cid2) == 3); 853 REQUIRE(timeline->getClipPtr(cid1)->clipState() == PlaylistState::VideoOnly); 854 REQUIRE(timeline->getClipPtr(cid2)->clipState() == PlaylistState::AudioOnly); 855 // we check that the av group was correctly created 856 REQUIRE(timeline->getGroupElements(cid1) == std::unordered_set<int>({cid1, cid2})); 857 int g1 = timeline->m_groups->getDirectAncestor(cid1); 858 REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({cid1, cid2})); 859 REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit); 860 }; 861 state(1, 0); 862 863 QString cpy_str = TimelineFunctions::copyClips(timeline, {cid1}); 864 865 REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 0)); 866 state(1, 0); 867 REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 4)); 868 state(1, 0); 869 870 // potentially annoying selection 871 REQUIRE(timeline->requestSetSelection({cid1})); 872 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2}); 873 874 // paste on same track, after clip 875 REQUIRE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 3 + 2 * l)); 876 int cid3 = timeline->getTrackById(tid1)->getClipByPosition(3 + 2 * l + 1); 877 REQUIRE(cid3 != -1); 878 int cid4 = timeline->m_groups->getSplitPartner(cid3); __anonf52080221c02(int count1, int count2) 879 auto state2 = [&](int count1, int count2) { 880 state(count1, count2); 881 REQUIRE(timeline->getClipTrackId(cid3) == tid1); 882 REQUIRE(timeline->getClipTrackId(cid4) == tid2); 883 REQUIRE(timeline->getClipPosition(cid3) == 3 + 2 * l); 884 REQUIRE(timeline->getClipPosition(cid4) == 3 + 2 * l); 885 REQUIRE(timeline->getClipPtr(cid3)->clipState() == PlaylistState::VideoOnly); 886 REQUIRE(timeline->getClipPtr(cid4)->clipState() == PlaylistState::AudioOnly); 887 // we check that the av group was correctly created 888 REQUIRE(timeline->getGroupElements(cid3) == std::unordered_set<int>({cid3, cid4})); 889 int g1 = timeline->m_groups->getDirectAncestor(cid3); 890 REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({cid3, cid4})); 891 REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit); 892 }; 893 state2(2, 0); 894 895 // potentially annoying selection 896 REQUIRE(timeline->requestSetSelection({cid1})); 897 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2}); 898 undoStack->undo(); 899 REQUIRE(timeline->requestClearSelection()); 900 state(1, 0); 901 902 // potentially annoying selection 903 REQUIRE(timeline->requestSetSelection({cid1})); 904 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2}); 905 undoStack->redo(); 906 REQUIRE(timeline->requestClearSelection()); 907 state2(2, 0); 908 909 // another potentially annoying selection 910 REQUIRE(timeline->requestSetSelection({cid1, cid3})); 911 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3, cid4}); 912 undoStack->undo(); 913 REQUIRE(timeline->requestClearSelection()); 914 state(1, 0); 915 REQUIRE(timeline->requestSetSelection({cid1})); 916 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2}); 917 undoStack->redo(); 918 REQUIRE(timeline->requestClearSelection()); 919 state2(2, 0); 920 921 // now, we copy the old clips as well as those we just pasted. Let's do it using a selection 922 REQUIRE(timeline->requestSetSelection({cid1, cid3})); 923 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3, cid4}); 924 // since everything is selected, everything should be copied here 925 cpy_str = TimelineFunctions::copyClips(timeline, {cid1}); 926 927 REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 0)); 928 state2(2, 0); 929 930 // parasitic selection 931 REQUIRE(timeline->requestSetSelection({cid1, cid3})); 932 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3, cid4}); 933 934 // We paste on the other track 935 REQUIRE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1b, 0)); 936 qDebug() << "track tid1 count" << timeline->getTrackClipsCount(tid1); 937 qDebug() << "track tid2 count" << timeline->getTrackClipsCount(tid2); 938 qDebug() << "track tid1b count" << timeline->getTrackClipsCount(tid1b); 939 qDebug() << "track tid2b count" << timeline->getTrackClipsCount(tid2b); 940 int cid5 = timeline->getTrackById(tid1b)->getClipByPosition(0); 941 REQUIRE(cid5 != -1); 942 int cid6 = timeline->m_groups->getSplitPartner(cid5); 943 REQUIRE(cid6 != -1); 944 int cid7 = timeline->getTrackById(tid1b)->getClipByPosition(2 * l + 1); 945 REQUIRE(cid7 != -1); 946 int cid8 = timeline->m_groups->getSplitPartner(cid7); 947 REQUIRE(cid8 != -1); __anonf52080221d02(int count1, int count2) 948 auto state3 = [&](int count1, int count2) { 949 state2(count1, count2); 950 REQUIRE(timeline->getClipTrackId(cid5) == tid1b); 951 REQUIRE(timeline->getClipTrackId(cid7) == tid1b); 952 REQUIRE(timeline->getClipTrackId(cid6) == tid2b); 953 REQUIRE(timeline->getClipTrackId(cid8) == tid2b); 954 REQUIRE(timeline->getClipPosition(cid5) == 0); 955 REQUIRE(timeline->getClipPosition(cid6) == 0); 956 REQUIRE(timeline->getClipPosition(cid7) == 2 * l); 957 REQUIRE(timeline->getClipPosition(cid8) == 2 * l); 958 REQUIRE(timeline->getClipPtr(cid5)->clipState() == PlaylistState::VideoOnly); 959 REQUIRE(timeline->getClipPtr(cid6)->clipState() == PlaylistState::AudioOnly); 960 REQUIRE(timeline->getClipPtr(cid7)->clipState() == PlaylistState::VideoOnly); 961 REQUIRE(timeline->getClipPtr(cid8)->clipState() == PlaylistState::AudioOnly); 962 // we check that the av group was correctly created 963 REQUIRE(timeline->getGroupElements(cid5) == std::unordered_set<int>({cid5, cid6})); 964 int g1 = timeline->m_groups->getDirectAncestor(cid5); 965 REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({cid5, cid6})); 966 REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit); 967 968 REQUIRE(timeline->getGroupElements(cid7) == std::unordered_set<int>({cid7, cid8})); 969 int g2 = timeline->m_groups->getDirectAncestor(cid7); 970 REQUIRE(timeline->m_groups->getDirectChildren(g2) == std::unordered_set<int>({cid7, cid8})); 971 REQUIRE(timeline->m_groups->getType(g2) == GroupType::AVSplit); 972 }; 973 state3(2, 2); 974 975 // parasitic selection 976 REQUIRE(timeline->requestSetSelection({cid1, cid3})); 977 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3, cid4}); 978 undoStack->undo(); 979 REQUIRE(timeline->requestClearSelection()); 980 state2(2, 0); 981 REQUIRE(timeline->requestSetSelection({cid1, cid3})); 982 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3, cid4}); 983 undoStack->redo(); 984 REQUIRE(timeline->requestClearSelection()); 985 state3(2, 2); 986 } 987 988 SECTION("Paste when tracks get deleted") 989 { __anonf52080221e02() 990 auto state0 = [&]() { 991 REQUIRE(timeline->checkConsistency()); 992 REQUIRE(timeline->getTrackClipsCount(tid1) == 0); 993 REQUIRE(timeline->getTrackClipsCount(tid2) == 0); 994 REQUIRE(timeline->getTrackClipsCount(tid1b) == 0); 995 REQUIRE(timeline->getTrackClipsCount(tid2b) == 0); 996 }; 997 state0(); 998 int cid1 = -1; 999 REQUIRE(timeline->requestClipInsertion(binId, tid1, 3, cid1, true, true, false)); 1000 timeline->getClipPlaytime(cid1); 1001 int cid2 = timeline->m_groups->getSplitPartner(cid1); 1002 __anonf52080221f02() 1003 auto state = [&]() { 1004 REQUIRE(timeline->checkConsistency()); 1005 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 1006 REQUIRE(timeline->getTrackClipsCount(tid2) == 1); 1007 REQUIRE(timeline->getTrackClipsCount(tid1b) == 0); 1008 REQUIRE(timeline->getTrackClipsCount(tid2b) == 0); 1009 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1010 REQUIRE(timeline->getClipTrackId(cid2) == tid2); 1011 REQUIRE(timeline->getClipPosition(cid1) == 3); 1012 REQUIRE(timeline->getClipPosition(cid2) == 3); 1013 REQUIRE(timeline->getClipPtr(cid1)->clipState() == PlaylistState::VideoOnly); 1014 REQUIRE(timeline->getClipPtr(cid2)->clipState() == PlaylistState::AudioOnly); 1015 // we check that the av group was correctly created 1016 REQUIRE(timeline->getGroupElements(cid1) == std::unordered_set<int>({cid1, cid2})); 1017 int g1 = timeline->m_groups->getDirectAncestor(cid1); 1018 REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({cid1, cid2})); 1019 REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit); 1020 }; 1021 state(); 1022 1023 QString cpy_str = TimelineFunctions::copyClips(timeline, {cid1}); 1024 1025 // we delete origin of the copy, paste should still be possible 1026 REQUIRE(timeline->requestItemDeletion(cid1)); 1027 state0(); 1028 1029 REQUIRE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 0)); 1030 int cid3 = timeline->getTrackById(tid1)->getClipByPosition(0); 1031 REQUIRE(cid3 != -1); 1032 int cid4 = timeline->m_groups->getSplitPartner(cid3); __anonf52080222002(int audio) 1033 auto state2 = [&](int audio) { 1034 REQUIRE(timeline->checkConsistency()); 1035 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 1036 REQUIRE(timeline->getTrackClipsCount(audio) == 1); 1037 REQUIRE(timeline->getTrackClipsCount(tid1b) == 0); 1038 REQUIRE(timeline->getClipTrackId(cid3) == tid1); 1039 REQUIRE(timeline->getClipTrackId(cid4) == audio); 1040 REQUIRE(timeline->getClipPosition(cid3) == 0); 1041 REQUIRE(timeline->getClipPosition(cid4) == 0); 1042 REQUIRE(timeline->getClipPtr(cid3)->clipState() == PlaylistState::VideoOnly); 1043 REQUIRE(timeline->getClipPtr(cid4)->clipState() == PlaylistState::AudioOnly); 1044 // we check that the av group was correctly created 1045 REQUIRE(timeline->getGroupElements(cid3) == std::unordered_set<int>({cid3, cid4})); 1046 int g1 = timeline->m_groups->getDirectAncestor(cid3); 1047 REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({cid3, cid4})); 1048 REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit); 1049 }; 1050 state2(tid2); 1051 1052 undoStack->undo(); 1053 state0(); 1054 undoStack->redo(); 1055 state2(tid2); 1056 undoStack->undo(); 1057 state0(); 1058 1059 // now, we remove all audio tracks, making paste impossible 1060 REQUIRE(timeline->requestTrackDeletion(tid2)); 1061 REQUIRE(timeline->requestTrackDeletion(tid2b)); 1062 REQUIRE_FALSE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 0)); 1063 1064 // undo one deletion 1065 undoStack->undo(); 1066 // now, tid2b should be a valid audio track 1067 REQUIRE(TimelineFunctions::pasteClips(timeline, cpy_str, tid1, 0)); 1068 cid3 = timeline->getTrackById(tid1)->getClipByPosition(0); 1069 REQUIRE(cid3 != -1); 1070 cid4 = timeline->m_groups->getSplitPartner(cid3); 1071 state2(tid2b); 1072 } 1073 binModel->clean(); 1074 pCore->m_projectManager = nullptr; 1075 } 1076 1077 TEST_CASE("Advanced trimming operations: Slip", "[TrimmingSlip]") 1078 { 1079 auto binModel = pCore->projectItemModel(); 1080 binModel->clean(); 1081 std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr); 1082 std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack); 1083 1084 // Here we do some trickery to enable testing. 1085 // We mock the project class so that the undoStack function returns our undoStack 1086 1087 Mock<ProjectManager> pmMock; 1088 When(Method(pmMock, undoStack)).AlwaysReturn(undoStack); 1089 When(Method(pmMock, cacheDir)).AlwaysReturn(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))); 1090 1091 ProjectManager &mocked = pmMock.get(); 1092 pCore->m_projectManager = &mocked; 1093 1094 // We also mock timeline object to spy few functions and mock others 1095 TimelineItemModel tim(&profile_trimming, undoStack); 1096 Mock<TimelineItemModel> timMock(tim); __anonf52080222102(...) 1097 auto timeline = std::shared_ptr<TimelineItemModel>(&timMock.get(), [](...) {}); 1098 TimelineItemModel::finishConstruct(timeline, guideModel); 1099 1100 RESET(timMock) 1101 1102 QString binId = createProducer(profile_trimming, "red", binModel); 1103 QString binId2 = createProducer(profile_trimming, "blue", binModel); 1104 1105 int tid1 = TrackModel::construct(timeline); 1106 int tid2 = TrackModel::construct(timeline); 1107 1108 int cid1 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 1109 int cid2 = ClipModel::construct(timeline, binId2, -1, PlaylistState::VideoOnly); 1110 int cid3 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 1111 int cid4 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 1112 int cid5 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 1113 1114 timeline->m_allClips[cid1]->m_endlessResize = false; 1115 timeline->m_allClips[cid2]->m_endlessResize = false; 1116 timeline->m_allClips[cid3]->m_endlessResize = false; 1117 timeline->m_allClips[cid4]->m_endlessResize = false; 1118 timeline->m_allClips[cid5]->m_endlessResize = false; 1119 1120 // sliping a fullsized clips should not to anything 1121 SECTION("Slip single fullsized clip") 1122 { 1123 REQUIRE(timeline->requestClipMove(cid1, tid1, 5)); 1124 int l = timeline->getClipPlaytime(cid1); __anonf52080222202() 1125 auto state = [&]() { 1126 REQUIRE(timeline->checkConsistency()); 1127 REQUIRE(timeline->getClipPlaytime(cid1) == l); 1128 REQUIRE(timeline->getClipPosition(cid1) == 5); 1129 REQUIRE(timeline->getClipPtr(cid1)->getIn() == 0); 1130 REQUIRE(timeline->getClipPtr(cid1)->getOut() == l - 1); 1131 }; 1132 state(); 1133 1134 REQUIRE(timeline->requestClipSlip(cid1, 3) == 3); 1135 state(); 1136 1137 REQUIRE(timeline->requestClipSlip(cid1, -3) == -3); 1138 state(); 1139 1140 undoStack->undo(); 1141 state(); 1142 undoStack->undo(); 1143 state(); 1144 1145 undoStack->redo(); 1146 state(); 1147 undoStack->redo(); 1148 state(); 1149 } 1150 1151 // slipping a downsized clip should only change the in and out point 1152 SECTION("Slip single cutted clip") 1153 { 1154 REQUIRE(timeline->requestClipMove(cid1, tid1, 5)); 1155 int l = timeline->getClipPlaytime(cid1); 1156 REQUIRE(timeline->requestItemResize(cid1, l - 5, true) == l - 5); 1157 REQUIRE(timeline->requestItemResize(cid1, l - 11, false) == l - 11); 1158 __anonf52080222302() 1159 auto state = [&]() { 1160 REQUIRE(timeline->checkConsistency()); 1161 REQUIRE(timeline->getClipPlaytime(cid1) == l - 11); 1162 REQUIRE(timeline->getClipPosition(cid1) == 5 + 6); 1163 REQUIRE(timeline->getClipPtr(cid1)->getIn() == 6); 1164 REQUIRE(timeline->getClipPtr(cid1)->getOut() == l - 6); 1165 }; 1166 state(); 1167 1168 REQUIRE(timeline->requestClipSlip(cid1, 3) == 3); __anonf52080222402() 1169 auto state2 = [&]() { 1170 REQUIRE(timeline->checkConsistency()); 1171 REQUIRE(timeline->getClipPlaytime(cid1) == l - 11); 1172 REQUIRE(timeline->getClipPosition(cid1) == 5 + 6); 1173 REQUIRE(timeline->getClipPtr(cid1)->getIn() == 3); 1174 REQUIRE(timeline->getClipPtr(cid1)->getOut() == l - 9); 1175 }; 1176 state2(); 1177 1178 REQUIRE(timeline->requestClipSlip(cid1, -3) == -3); 1179 state(); 1180 1181 undoStack->undo(); 1182 state2(); 1183 undoStack->undo(); 1184 state(); 1185 1186 undoStack->redo(); 1187 state2(); 1188 undoStack->redo(); 1189 state(); 1190 1191 } 1192 1193 // if offset is bigger than the borders use the biggest possible offset without going beyond the borders 1194 SECTION("Slip beyond borders") 1195 { 1196 REQUIRE(timeline->requestClipMove(cid1, tid1, 5)); 1197 int l = timeline->getClipPlaytime(cid1); 1198 1199 REQUIRE(timeline->getClipPlaytime(cid1) == l); 1200 REQUIRE(timeline->requestItemResize(cid1, l - 5, true) == l - 5); 1201 REQUIRE(timeline->requestItemResize(cid1, l - 11, false) == l - 11); 1202 REQUIRE(timeline->getClipPtr(cid1)->getOut() == l - 6); 1203 1204 __anonf52080222502() 1205 auto state = [&]() { 1206 REQUIRE(timeline->checkConsistency()); 1207 REQUIRE(timeline->getClipPlaytime(cid1) == l - 11); 1208 REQUIRE(timeline->getClipPosition(cid1) == 5 + 6); 1209 REQUIRE(timeline->getClipPtr(cid1)->getIn() == 6); 1210 REQUIRE(timeline->getClipPtr(cid1)->getOut() == l - 6); 1211 }; 1212 state(); 1213 1214 // left border 1215 REQUIRE(timeline->requestClipSlip(cid1, 30) == 30); __anonf52080222602() 1216 auto state2 = [&]() { 1217 REQUIRE(timeline->checkConsistency()); 1218 REQUIRE(timeline->getClipPlaytime(cid1) == l - 11); 1219 REQUIRE(timeline->getClipPosition(cid1) == 5 + 6); 1220 REQUIRE(timeline->getClipPtr(cid1)->getIn() == 0); 1221 REQUIRE(timeline->getClipPtr(cid1)->getOut() == l - 12); 1222 }; 1223 state2(); 1224 1225 // right border 1226 REQUIRE(timeline->requestClipSlip(cid1, -30) == -30); __anonf52080222702() 1227 auto state3 = [&]() { 1228 REQUIRE(timeline->checkConsistency()); 1229 REQUIRE(timeline->getClipPlaytime(cid1) == l - 11); 1230 REQUIRE(timeline->getClipPosition(cid1) == 5 + 6); 1231 REQUIRE(timeline->getClipPtr(cid1)->getIn() == 11); 1232 REQUIRE(timeline->getClipPtr(cid1)->getOut() == l - 1); 1233 }; 1234 state3(); 1235 1236 undoStack->undo(); 1237 state2(); 1238 undoStack->undo(); 1239 state(); 1240 1241 undoStack->redo(); 1242 state2(); 1243 undoStack->redo(); 1244 state3(); 1245 } 1246 1247 // slipping one clip of a group should slip all members 1248 SECTION("Slip group") 1249 { 1250 REQUIRE(timeline->requestClipMove(cid1, tid1, 5)); 1251 int l1 = timeline->getClipPlaytime(cid1); 1252 REQUIRE(timeline->requestItemResize(cid1, l1 - 5, true) == l1 - 5); 1253 REQUIRE(timeline->requestItemResize(cid1, l1 - 11, false) == l1 - 11); 1254 1255 REQUIRE(timeline->requestClipMove(cid2, tid1, 50)); 1256 int l2 = timeline->getClipPlaytime(cid2); 1257 REQUIRE(timeline->requestItemResize(cid2, l2 - 11, false) == l2 - 11); 1258 1259 REQUIRE(timeline->requestClipMove(cid3, tid2, 25)); 1260 int l3 = timeline->getClipPlaytime(cid3); 1261 REQUIRE(timeline->requestItemResize(cid3, l3 - 5, true) == l3 - 5); 1262 1263 REQUIRE(timeline->requestClipMove(cid4, tid2, 0)); 1264 int l4 = timeline->getClipPlaytime(cid4); 1265 REQUIRE(timeline->requestItemResize(cid4, l4 - 9, true) == l4 - 9); 1266 REQUIRE(timeline->requestItemResize(cid4, l4 - 17, false) == l4 - 17); 1267 1268 REQUIRE(timeline->requestClipMove(cid5, tid2, 60)); 1269 int l5 = timeline->getClipPlaytime(cid5); 1270 int gid1 = timeline->requestClipsGroup(std::unordered_set<int>({cid1, cid2, cid3, cid4, cid5}), true, GroupType::Normal); 1271 REQUIRE(gid1 > -1); 1272 __anonf52080222802() 1273 auto state = [&]() { 1274 REQUIRE(timeline->checkConsistency()); 1275 REQUIRE(timeline->getClipPlaytime(cid1) == l1 - 11); 1276 REQUIRE(timeline->getClipPosition(cid1) == 5 + 6); 1277 REQUIRE(timeline->getClipPtr(cid1)->getIn() == 6); 1278 REQUIRE(timeline->getClipPtr(cid1)->getOut() == l1 - 6); 1279 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1280 1281 REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 11); 1282 REQUIRE(timeline->getClipPosition(cid2) == 50 + 11); 1283 REQUIRE(timeline->getClipPtr(cid2)->getIn() == 11); 1284 REQUIRE(timeline->getClipPtr(cid2)->getOut() == l2 -1); 1285 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 1286 1287 REQUIRE(timeline->getClipPlaytime(cid3) == l3 - 5); 1288 REQUIRE(timeline->getClipPosition(cid3) == 25); 1289 REQUIRE(timeline->getClipPtr(cid3)->getIn() == 0); 1290 REQUIRE(timeline->getClipPtr(cid3)->getOut() == l3 - 6); 1291 REQUIRE(timeline->getClipTrackId(cid3) == tid2); 1292 1293 REQUIRE(timeline->getClipPlaytime(cid4) == l4 - 17); 1294 REQUIRE(timeline->getClipPosition(cid4) == 8); 1295 REQUIRE(timeline->getClipPtr(cid4)->getIn() == 8); 1296 REQUIRE(timeline->getClipPtr(cid4)->getOut() == l4 - 10); 1297 REQUIRE(timeline->getClipTrackId(cid4) == tid2); 1298 1299 REQUIRE(timeline->getClipPlaytime(cid5) == l5); 1300 REQUIRE(timeline->getClipPosition(cid5) == 60); 1301 REQUIRE(timeline->getClipPtr(cid5)->getIn() == 0); 1302 REQUIRE(timeline->getClipPtr(cid5)->getOut() == l5 - 1); 1303 REQUIRE(timeline->getClipTrackId(cid5) == tid2); 1304 1305 REQUIRE(timeline->m_groups->getLeaves(gid1) == std::unordered_set<int>({cid1, cid2, cid3, cid4, cid5})); 1306 }; 1307 state(); 1308 1309 REQUIRE(timeline->requestClipSlip(cid1, 3) == 3); 1310 __anonf52080222902() 1311 auto state2 = [&]() { 1312 REQUIRE(timeline->checkConsistency()); 1313 REQUIRE(timeline->getClipPlaytime(cid1) == l1 - 11); 1314 REQUIRE(timeline->getClipPosition(cid1) == 5 + 6); 1315 REQUIRE(timeline->getClipPtr(cid1)->getIn() == 3); 1316 REQUIRE(timeline->getClipPtr(cid1)->getOut() == l1 - 9); 1317 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1318 1319 REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 11); 1320 REQUIRE(timeline->getClipPosition(cid2) == 50 + 11); 1321 REQUIRE(timeline->getClipPtr(cid2)->getIn() == 8); 1322 REQUIRE(timeline->getClipPtr(cid2)->getOut() == l2 - 4); 1323 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 1324 1325 REQUIRE(timeline->getClipPlaytime(cid3) == l3 - 5); 1326 REQUIRE(timeline->getClipPosition(cid3) == 25); 1327 REQUIRE(timeline->getClipPtr(cid3)->getIn() == 0); 1328 REQUIRE(timeline->getClipPtr(cid3)->getOut() == l3 - 6); 1329 REQUIRE(timeline->getClipTrackId(cid3) == tid2); 1330 1331 REQUIRE(timeline->getClipPlaytime(cid4) == l4 - 17); 1332 REQUIRE(timeline->getClipPosition(cid4) == 8); 1333 REQUIRE(timeline->getClipPtr(cid4)->getIn() == 5); 1334 REQUIRE(timeline->getClipPtr(cid4)->getOut() == l4 - 13); 1335 REQUIRE(timeline->getClipTrackId(cid4) == tid2); 1336 1337 REQUIRE(timeline->getClipPlaytime(cid5) == l5); 1338 REQUIRE(timeline->getClipPosition(cid5) == 60); 1339 REQUIRE(timeline->getClipPtr(cid5)->getIn() == 0); 1340 REQUIRE(timeline->getClipPtr(cid5)->getOut() == l5 - 1); 1341 REQUIRE(timeline->getClipTrackId(cid5) == tid2); 1342 1343 REQUIRE(timeline->m_groups->getLeaves(gid1) == std::unordered_set<int>({cid1, cid2, cid3, cid4, cid5})); 1344 }; 1345 state2(); 1346 1347 REQUIRE(timeline->requestClipSlip(cid4, 30) == 30); 1348 __anonf52080222a02() 1349 auto state3 = [&]() { 1350 REQUIRE(timeline->checkConsistency()); 1351 REQUIRE(timeline->getClipPlaytime(cid1) == l1 - 11); 1352 REQUIRE(timeline->getClipPosition(cid1) == 5 + 6); 1353 REQUIRE(timeline->getClipPtr(cid1)->getIn() == 0); 1354 REQUIRE(timeline->getClipPtr(cid1)->getOut() == l1 - 12); 1355 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1356 1357 REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 11); 1358 REQUIRE(timeline->getClipPosition(cid2) == 50 + 11); 1359 REQUIRE(timeline->getClipPtr(cid2)->getIn() == 0); 1360 REQUIRE(timeline->getClipPtr(cid2)->getOut() == l2 - 12); 1361 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 1362 1363 REQUIRE(timeline->getClipPlaytime(cid3) == l3 - 5); 1364 REQUIRE(timeline->getClipPosition(cid3) == 25); 1365 REQUIRE(timeline->getClipPtr(cid3)->getIn() == 0); 1366 REQUIRE(timeline->getClipPtr(cid3)->getOut() == l3 - 6); 1367 REQUIRE(timeline->getClipTrackId(cid3) == tid2); 1368 1369 REQUIRE(timeline->getClipPlaytime(cid4) == l4 - 17); 1370 REQUIRE(timeline->getClipPosition(cid4) == 8); 1371 REQUIRE(timeline->getClipPtr(cid4)->getIn() == 0); 1372 REQUIRE(timeline->getClipPtr(cid4)->getOut() == l4 - 18); 1373 REQUIRE(timeline->getClipTrackId(cid4) == tid2); 1374 1375 REQUIRE(timeline->getClipPlaytime(cid5) == l5); 1376 REQUIRE(timeline->getClipPosition(cid5) == 60); 1377 REQUIRE(timeline->getClipPtr(cid5)->getIn() == 0); 1378 REQUIRE(timeline->getClipPtr(cid5)->getOut() == l5 - 1); 1379 REQUIRE(timeline->getClipTrackId(cid5) == tid2); 1380 1381 REQUIRE(timeline->m_groups->getLeaves(gid1) == std::unordered_set<int>({cid1, cid2, cid3, cid4, cid5})); 1382 }; 1383 state3(); 1384 1385 undoStack->undo(); 1386 state2(); 1387 undoStack->undo(); 1388 state(); 1389 1390 undoStack->redo(); 1391 state2(); 1392 undoStack->redo(); 1393 state3(); 1394 } 1395 1396 binModel->clean(); 1397 pCore->m_projectManager = nullptr; 1398 } 1399 1400 TEST_CASE("Advanced trimming operations: Ripple", "[TrimmingRipple]") 1401 { 1402 auto binModel = pCore->projectItemModel(); 1403 binModel->clean(); 1404 std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr); 1405 std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack); 1406 1407 // Here we do some trickery to enable testing. 1408 // We mock the project class so that the undoStack function returns our undoStack 1409 1410 Mock<ProjectManager> pmMock; 1411 When(Method(pmMock, undoStack)).AlwaysReturn(undoStack); 1412 When(Method(pmMock, cacheDir)).AlwaysReturn(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))); 1413 1414 ProjectManager &mocked = pmMock.get(); 1415 pCore->m_projectManager = &mocked; 1416 1417 // We also mock timeline object to spy few functions and mock others 1418 TimelineItemModel tim(&profile_trimming, undoStack); 1419 Mock<TimelineItemModel> timMock(tim); __anonf52080222b02(...) 1420 auto timeline = std::shared_ptr<TimelineItemModel>(&timMock.get(), [](...) {}); 1421 TimelineItemModel::finishConstruct(timeline, guideModel); 1422 1423 RESET(timMock) 1424 1425 QString binId = createProducer(profile_trimming, "red", binModel); 1426 QString binId2 = createProducer(profile_trimming, "blue", binModel); 1427 1428 int tid1 = TrackModel::construct(timeline); 1429 int tid2 = TrackModel::construct(timeline); 1430 1431 int cid1 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 1432 int cid2 = ClipModel::construct(timeline, binId2, -1, PlaylistState::VideoOnly); 1433 int cid3 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 1434 int cid4 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 1435 int cid5 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 1436 int cid6 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 1437 1438 timeline->m_allClips[cid1]->m_endlessResize = false; 1439 timeline->m_allClips[cid2]->m_endlessResize = false; 1440 timeline->m_allClips[cid3]->m_endlessResize = false; 1441 timeline->m_allClips[cid4]->m_endlessResize = false; 1442 timeline->m_allClips[cid5]->m_endlessResize = false; 1443 1444 // ripple resize a fullsized clip longer should not to anything 1445 SECTION("Ripple resize single fullsized clip (longer)") 1446 { 1447 REQUIRE(timeline->requestClipMove(cid1, tid1, 5)); 1448 int l1 = timeline->getClipPlaytime(cid1); 1449 1450 REQUIRE(timeline->requestClipMove(cid2, tid1, 50)); 1451 int l2 = timeline->getClipPlaytime(cid2); 1452 1453 REQUIRE(timeline->requestClipMove(cid3, tid1, 80)); 1454 int l3 = timeline->getClipPlaytime(cid3); 1455 __anonf52080222c02() 1456 auto state = [&]() { 1457 REQUIRE(timeline->checkConsistency()); 1458 REQUIRE(timeline->getClipPlaytime(cid1) == l1); 1459 REQUIRE(timeline->getClipPosition(cid1) == 5); 1460 REQUIRE(timeline->getClipPtr(cid1)->getIn() == 0); 1461 REQUIRE(timeline->getClipPtr(cid1)->getOut() == l1 - 1); 1462 REQUIRE(timeline->getClipPlaytime(cid2) == l2); 1463 REQUIRE(timeline->getClipPosition(cid2) == 50); 1464 REQUIRE(timeline->getClipPtr(cid2)->getIn() == 0); 1465 REQUIRE(timeline->getClipPtr(cid2)->getOut() == l2 - 1); 1466 REQUIRE(timeline->getClipPlaytime(cid3) == l3); 1467 REQUIRE(timeline->getClipPosition(cid3) == 80); 1468 REQUIRE(timeline->getClipPtr(cid3)->getIn() == 0); 1469 REQUIRE(timeline->getClipPtr(cid3)->getOut() == l3 - 1); 1470 }; 1471 state(); 1472 1473 REQUIRE(timeline->requestItemRippleResize(timeline, cid1, l1 + 5, true)); 1474 state(); 1475 1476 REQUIRE(timeline->requestItemRippleResize(timeline, cid1, l1 + 5, false)); 1477 state(); 1478 1479 REQUIRE(timeline->requestItemRippleResize(timeline, cid2, l2 + 5, true)); 1480 REQUIRE(timeline->requestItemRippleResize(timeline, cid1, l2 + 5, false)); 1481 state(); 1482 1483 REQUIRE(timeline->requestItemRippleResize(timeline, cid3, l3 + 5, true)); 1484 REQUIRE(timeline->requestItemRippleResize(timeline, cid3, l3 + 5, false)); 1485 state(); 1486 1487 undoStack->undo(); 1488 state(); 1489 undoStack->undo(); 1490 state(); 1491 1492 undoStack->redo(); 1493 state(); 1494 undoStack->redo(); 1495 state(); 1496 } 1497 1498 // ripple resize a fullsized clip shorter should resize the clip and move following clips 1499 SECTION("Ripple resize single fullsized clip (shorter)") 1500 { 1501 REQUIRE(timeline->requestClipMove(cid1, tid1, 5)); 1502 int l1 = timeline->getClipPlaytime(cid1); 1503 1504 REQUIRE(timeline->requestClipMove(cid2, tid1, 50)); 1505 int l2 = timeline->getClipPlaytime(cid2); 1506 1507 REQUIRE(timeline->requestClipMove(cid3, tid1, 80)); 1508 int l3 = timeline->getClipPlaytime(cid3); 1509 __anonf52080222d02() 1510 auto stateA1 = [&]() { 1511 REQUIRE(timeline->checkConsistency()); 1512 REQUIRE(timeline->getClipPlaytime(cid1) == l1); 1513 REQUIRE(timeline->getClipPosition(cid1) == 5); 1514 REQUIRE(timeline->getClipPtr(cid1)->getIn() == 0); 1515 REQUIRE(timeline->getClipPtr(cid1)->getOut() == l1 - 1); 1516 }; __anonf52080222e02() 1517 auto stateA2 = [&]() { 1518 REQUIRE(timeline->checkConsistency()); 1519 REQUIRE(timeline->getClipPlaytime(cid2) == l2); 1520 REQUIRE(timeline->getClipPosition(cid2) == 50); 1521 REQUIRE(timeline->getClipPtr(cid2)->getIn() == 0); 1522 REQUIRE(timeline->getClipPtr(cid2)->getOut() == l2 - 1); 1523 1524 REQUIRE(timeline->checkConsistency()); 1525 REQUIRE(timeline->getClipPlaytime(cid3) == l3); 1526 REQUIRE(timeline->getClipPosition(cid3) == 80); 1527 REQUIRE(timeline->getClipPtr(cid3)->getIn() == 0); 1528 REQUIRE(timeline->getClipPtr(cid3)->getOut() == l3 - 1); 1529 }; 1530 stateA1(); 1531 stateA2(); 1532 __anonf52080222f02() 1533 auto stateB = [&]() { 1534 REQUIRE(timeline->checkConsistency()); 1535 REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 5); 1536 REQUIRE(timeline->getClipPosition(cid2) == 50); 1537 REQUIRE(timeline->getClipPtr(cid2)->getIn() == 0); 1538 REQUIRE(timeline->getClipPtr(cid2)->getOut() == l2 - 6); 1539 1540 REQUIRE(timeline->getClipPlaytime(cid3) == l3); 1541 REQUIRE(timeline->getClipPosition(cid3) == 75); 1542 REQUIRE(timeline->getClipPtr(cid3)->getIn() == 0); 1543 REQUIRE(timeline->getClipPtr(cid3)->getOut() == l3 - 1); 1544 }; 1545 REQUIRE(timeline->requestItemRippleResize(timeline, cid2, l2 - 5, true) == l2 - 5); 1546 stateA1(); 1547 stateB(); 1548 __anonf52080223002() 1549 auto stateC = [&]() { 1550 REQUIRE(timeline->checkConsistency()); 1551 REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 8); 1552 REQUIRE(timeline->getClipPosition(cid2) == 50); 1553 REQUIRE(timeline->getClipPtr(cid2)->getIn() == 3); 1554 REQUIRE(timeline->getClipPtr(cid2)->getOut() == l2 - 6); 1555 1556 REQUIRE(timeline->getClipPlaytime(cid3) == l3); 1557 REQUIRE(timeline->getClipPosition(cid3) == 72); 1558 REQUIRE(timeline->getClipPtr(cid3)->getIn() == 0); 1559 REQUIRE(timeline->getClipPtr(cid3)->getOut() == l3 - 1); 1560 }; 1561 1562 REQUIRE(timeline->requestItemRippleResize(timeline, cid2, l2 - 8, false)); 1563 stateA1(); 1564 stateC(); 1565 1566 undoStack->undo(); 1567 stateA1(); 1568 stateB(); 1569 1570 undoStack->undo(); 1571 stateA1(); 1572 stateA2(); 1573 1574 undoStack->redo(); 1575 stateA1(); 1576 stateB(); 1577 1578 undoStack->redo(); 1579 stateA1(); 1580 stateC(); 1581 } 1582 1583 // ripple resize a grouped clip should move the affect all group partners on other tracks with same position as well 1584 SECTION("Ripple resize fullsized multitrack group (shorter)") 1585 { 1586 REQUIRE(timeline->requestClipMove(cid1, tid1, 5)); 1587 int l1 = timeline->getClipPlaytime(cid1); 1588 1589 REQUIRE(timeline->requestClipMove(cid2, tid1, 50)); 1590 int l2 = timeline->getClipPlaytime(cid2); 1591 1592 REQUIRE(timeline->requestClipMove(cid3, tid1, 80)); 1593 int l3 = timeline->getClipPlaytime(cid3); 1594 1595 REQUIRE(timeline->requestClipMove(cid4, tid2, 5)); 1596 int l4 = timeline->getClipPlaytime(cid4); 1597 REQUIRE(l4 == l1); 1598 int gid1 = timeline->requestClipsGroup(std::unordered_set<int>({cid1, cid4}), true, GroupType::Normal); 1599 1600 REQUIRE(timeline->requestClipMove(cid5, tid2, 50)); 1601 int l5 = timeline->getClipPlaytime(cid5); 1602 REQUIRE(l5 == l2); 1603 int gid2 = timeline->requestClipsGroup(std::unordered_set<int>({cid2, cid5}), true, GroupType::Normal); 1604 1605 REQUIRE(timeline->requestClipMove(cid6, tid2, 80)); 1606 int l6 = timeline->getClipPlaytime(cid6); 1607 REQUIRE(l6 == l3); 1608 int gid3 = timeline->requestClipsGroup(std::unordered_set<int>({cid3, cid6}), true, GroupType::Normal); 1609 __anonf52080223102() 1610 auto stateA1 = [&]() { 1611 REQUIRE(timeline->checkConsistency()); 1612 REQUIRE(timeline->getClipPlaytime(cid1) == l1); 1613 REQUIRE(timeline->getClipPosition(cid1) == 5); 1614 REQUIRE(timeline->getClipPtr(cid1)->getIn() == 0); 1615 REQUIRE(timeline->getClipPtr(cid1)->getOut() == l1 - 1); 1616 1617 REQUIRE(timeline->checkConsistency()); 1618 REQUIRE(timeline->getClipPlaytime(cid4) == timeline->getClipPlaytime(cid1)); 1619 REQUIRE(timeline->getClipPosition(cid4) == timeline->getClipPosition(cid1)); 1620 REQUIRE(timeline->getClipPtr(cid4)->getIn() == timeline->getClipPtr(cid1)->getIn()); 1621 REQUIRE(timeline->getClipPtr(cid4)->getOut() == timeline->getClipPtr(cid1)->getOut()); 1622 }; __anonf52080223202() 1623 auto stateA2 = [&]() { 1624 REQUIRE(timeline->checkConsistency()); 1625 REQUIRE(timeline->getClipPlaytime(cid2) == l2); 1626 REQUIRE(timeline->getClipPosition(cid2) == 50); 1627 REQUIRE(timeline->getClipPtr(cid2)->getIn() == 0); 1628 REQUIRE(timeline->getClipPtr(cid2)->getOut() == l2 - 1); 1629 1630 REQUIRE(timeline->checkConsistency()); 1631 REQUIRE(timeline->getClipPlaytime(cid3) == l3); 1632 REQUIRE(timeline->getClipPosition(cid3) == 80); 1633 REQUIRE(timeline->getClipPtr(cid3)->getIn() == 0); 1634 REQUIRE(timeline->getClipPtr(cid3)->getOut() == l3 - 1); 1635 1636 REQUIRE(timeline->checkConsistency()); 1637 REQUIRE(timeline->getClipPlaytime(cid5) == timeline->getClipPlaytime(cid2)); 1638 REQUIRE(timeline->getClipPosition(cid5) == timeline->getClipPosition(cid2)); 1639 REQUIRE(timeline->getClipPtr(cid5)->getIn() == timeline->getClipPtr(cid2)->getIn()); 1640 REQUIRE(timeline->getClipPtr(cid5)->getOut() == timeline->getClipPtr(cid2)->getOut()); 1641 1642 REQUIRE(timeline->checkConsistency()); 1643 REQUIRE(timeline->getClipPlaytime(cid6) == timeline->getClipPlaytime(cid3)); 1644 REQUIRE(timeline->getClipPosition(cid6) == timeline->getClipPosition(cid3)); 1645 REQUIRE(timeline->getClipPtr(cid6)->getIn() == timeline->getClipPtr(cid3)->getIn()); 1646 REQUIRE(timeline->getClipPtr(cid6)->getOut() == timeline->getClipPtr(cid3)->getOut()); 1647 }; 1648 stateA1(); 1649 stateA2(); 1650 __anonf52080223302() 1651 auto stateB = [&]() { 1652 REQUIRE(timeline->checkConsistency()); 1653 REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 5); 1654 REQUIRE(timeline->getClipPosition(cid2) == 50); 1655 REQUIRE(timeline->getClipPtr(cid2)->getIn() == 0); 1656 REQUIRE(timeline->getClipPtr(cid2)->getOut() == l2 - 6); 1657 1658 REQUIRE(timeline->getClipPlaytime(cid3) == l3); 1659 REQUIRE(timeline->getClipPosition(cid3) == 75); 1660 REQUIRE(timeline->getClipPtr(cid3)->getIn() == 0); 1661 REQUIRE(timeline->getClipPtr(cid3)->getOut() == l3 - 1); 1662 1663 REQUIRE(timeline->checkConsistency()); 1664 REQUIRE(timeline->getClipPlaytime(cid5) == timeline->getClipPlaytime(cid2)); 1665 REQUIRE(timeline->getClipPosition(cid5) == timeline->getClipPosition(cid2)); 1666 REQUIRE(timeline->getClipPtr(cid5)->getIn() == timeline->getClipPtr(cid2)->getIn()); 1667 REQUIRE(timeline->getClipPtr(cid5)->getOut() == timeline->getClipPtr(cid2)->getOut()); 1668 1669 REQUIRE(timeline->checkConsistency()); 1670 REQUIRE(timeline->getClipPlaytime(cid6) == timeline->getClipPlaytime(cid3)); 1671 REQUIRE(timeline->getClipPosition(cid6) == timeline->getClipPosition(cid3)); 1672 REQUIRE(timeline->getClipPtr(cid6)->getIn() == timeline->getClipPtr(cid3)->getIn()); 1673 REQUIRE(timeline->getClipPtr(cid6)->getOut() == timeline->getClipPtr(cid3)->getOut()); 1674 }; 1675 REQUIRE(timeline->requestItemRippleResize(timeline, cid2, l2 - 5, true) == l2 - 5); 1676 stateA1(); 1677 stateB(); 1678 __anonf52080223402() 1679 auto stateC = [&]() { 1680 REQUIRE(timeline->checkConsistency()); 1681 REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 8); 1682 REQUIRE(timeline->getClipPosition(cid2) == 50); 1683 REQUIRE(timeline->getClipPtr(cid2)->getIn() == 3); 1684 REQUIRE(timeline->getClipPtr(cid2)->getOut() == l2 - 6); 1685 1686 REQUIRE(timeline->getClipPlaytime(cid3) == l3); 1687 REQUIRE(timeline->getClipPosition(cid3) == 72); 1688 REQUIRE(timeline->getClipPtr(cid3)->getIn() == 0); 1689 REQUIRE(timeline->getClipPtr(cid3)->getOut() == l3 - 1); 1690 1691 REQUIRE(timeline->checkConsistency()); 1692 REQUIRE(timeline->getClipPlaytime(cid5) == timeline->getClipPlaytime(cid2)); 1693 REQUIRE(timeline->getClipPosition(cid5) == timeline->getClipPosition(cid2)); 1694 REQUIRE(timeline->getClipPtr(cid5)->getIn() == timeline->getClipPtr(cid2)->getIn()); 1695 REQUIRE(timeline->getClipPtr(cid5)->getOut() == timeline->getClipPtr(cid2)->getOut()); 1696 1697 REQUIRE(timeline->checkConsistency()); 1698 REQUIRE(timeline->getClipPlaytime(cid6) == timeline->getClipPlaytime(cid3)); 1699 REQUIRE(timeline->getClipPosition(cid6) == timeline->getClipPosition(cid3)); 1700 REQUIRE(timeline->getClipPtr(cid6)->getIn() == timeline->getClipPtr(cid3)->getIn()); 1701 REQUIRE(timeline->getClipPtr(cid6)->getOut() == timeline->getClipPtr(cid3)->getOut()); 1702 }; 1703 1704 REQUIRE(timeline->requestItemRippleResize(timeline, cid2, l2 - 8, false)); 1705 stateA1(); 1706 stateC(); 1707 1708 undoStack->undo(); 1709 stateA1(); 1710 stateB(); 1711 1712 undoStack->undo(); 1713 stateA1(); 1714 stateA2(); 1715 1716 undoStack->redo(); 1717 stateA1(); 1718 stateB(); 1719 1720 undoStack->redo(); 1721 stateA1(); 1722 stateC(); 1723 } 1724 1725 SECTION("Ripple resize fullsized single track group (shorter)") 1726 { 1727 REQUIRE(timeline->requestClipMove(cid1, tid1, 5)); 1728 int l1 = timeline->getClipPlaytime(cid1); 1729 1730 REQUIRE(timeline->requestClipMove(cid2, tid1, 50)); 1731 int l2 = timeline->getClipPlaytime(cid2); 1732 1733 REQUIRE(timeline->requestClipMove(cid3, tid1, 80)); 1734 int l3 = timeline->getClipPlaytime(cid3); 1735 1736 int gid1 = timeline->requestClipsGroup(std::unordered_set<int>({cid1, cid2, cid3}), true, GroupType::Normal); 1737 __anonf52080223502() 1738 auto stateA1 = [&]() { 1739 REQUIRE(timeline->checkConsistency()); 1740 REQUIRE(timeline->getClipPlaytime(cid1) == l1); 1741 REQUIRE(timeline->getClipPosition(cid1) == 5); 1742 REQUIRE(timeline->getClipPtr(cid1)->getIn() == 0); 1743 REQUIRE(timeline->getClipPtr(cid1)->getOut() == l1 - 1); 1744 1745 REQUIRE(timeline->m_groups->getLeaves(gid1) == std::unordered_set<int>({cid1, cid2, cid3})); 1746 }; __anonf52080223602() 1747 auto stateA2 = [&]() { 1748 REQUIRE(timeline->checkConsistency()); 1749 REQUIRE(timeline->getClipPlaytime(cid2) == l2); 1750 REQUIRE(timeline->getClipPosition(cid2) == 50); 1751 REQUIRE(timeline->getClipPtr(cid2)->getIn() == 0); 1752 REQUIRE(timeline->getClipPtr(cid2)->getOut() == l2 - 1); 1753 1754 REQUIRE(timeline->checkConsistency()); 1755 REQUIRE(timeline->getClipPlaytime(cid3) == l3); 1756 REQUIRE(timeline->getClipPosition(cid3) == 80); 1757 REQUIRE(timeline->getClipPtr(cid3)->getIn() == 0); 1758 REQUIRE(timeline->getClipPtr(cid3)->getOut() == l3 - 1); 1759 1760 REQUIRE(timeline->m_groups->getLeaves(gid1) == std::unordered_set<int>({cid1, cid2, cid3})); 1761 }; 1762 stateA1(); 1763 stateA2(); 1764 __anonf52080223702() 1765 auto stateB = [&]() { 1766 REQUIRE(timeline->checkConsistency()); 1767 REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 5); 1768 REQUIRE(timeline->getClipPosition(cid2) == 50); 1769 REQUIRE(timeline->getClipPtr(cid2)->getIn() == 0); 1770 REQUIRE(timeline->getClipPtr(cid2)->getOut() == l2 - 6); 1771 1772 REQUIRE(timeline->getClipPlaytime(cid3) == l3); 1773 REQUIRE(timeline->getClipPosition(cid3) == 75); 1774 REQUIRE(timeline->getClipPtr(cid3)->getIn() == 0); 1775 REQUIRE(timeline->getClipPtr(cid3)->getOut() == l3 - 1); 1776 1777 REQUIRE(timeline->m_groups->getLeaves(gid1) == std::unordered_set<int>({cid1, cid2, cid3})); 1778 }; 1779 REQUIRE(timeline->requestItemRippleResize(timeline, cid2, l2 - 5, true) == l2 - 5); 1780 stateA1(); 1781 stateB(); 1782 __anonf52080223802() 1783 auto stateC = [&]() { 1784 REQUIRE(timeline->checkConsistency()); 1785 REQUIRE(timeline->getClipPlaytime(cid2) == l2 - 8); 1786 REQUIRE(timeline->getClipPosition(cid2) == 50); 1787 REQUIRE(timeline->getClipPtr(cid2)->getIn() == 3); 1788 REQUIRE(timeline->getClipPtr(cid2)->getOut() == l2 - 6); 1789 1790 REQUIRE(timeline->getClipPlaytime(cid3) == l3); 1791 REQUIRE(timeline->getClipPosition(cid3) == 72); 1792 REQUIRE(timeline->getClipPtr(cid3)->getIn() == 0); 1793 REQUIRE(timeline->getClipPtr(cid3)->getOut() == l3 - 1); 1794 1795 REQUIRE(timeline->m_groups->getLeaves(gid1) == std::unordered_set<int>({cid1, cid2, cid3})); 1796 }; 1797 1798 REQUIRE(timeline->requestItemRippleResize(timeline, cid2, l2 - 8, false)); 1799 stateA1(); 1800 stateC(); 1801 1802 undoStack->undo(); 1803 stateA1(); 1804 stateB(); 1805 1806 undoStack->undo(); 1807 stateA1(); 1808 stateA2(); 1809 1810 undoStack->redo(); 1811 stateA1(); 1812 stateB(); 1813 1814 undoStack->redo(); 1815 stateA1(); 1816 stateC(); 1817 } 1818 1819 binModel->clean(); 1820 pCore->m_projectManager = nullptr; 1821 } 1822 1823