1 #include "test_utils.hpp" 2 3 using namespace fakeit; 4 std::default_random_engine g(42); 5 Mlt::Profile profile_model; 6 7 TEST_CASE("Basic creation/deletion of a track", "[TrackModel]") 8 { 9 auto binModel = pCore->projectItemModel(); 10 std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr); 11 std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack); 12 13 // Here we do some trickery to enable testing. 14 // We mock the project class so that the undoStack function returns our undoStack 15 16 Mock<ProjectManager> pmMock; 17 When(Method(pmMock, undoStack)).AlwaysReturn(undoStack); 18 When(Method(pmMock, cacheDir)).AlwaysReturn(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))); 19 ProjectManager &mocked = pmMock.get(); 20 pCore->m_projectManager = &mocked; 21 22 // We also mock timeline object to spy few functions and mock others 23 TimelineItemModel tim(&profile_model, undoStack); 24 Mock<TimelineItemModel> timMock(tim); __anond6fdc6cc0102(...) 25 auto timeline = std::shared_ptr<TimelineItemModel>(&timMock.get(), [](...) {}); 26 TimelineItemModel::finishConstruct(timeline, guideModel); 27 28 Fake(Method(timMock, adjustAssetRange)); 29 30 // This is faked to allow to count calls 31 32 int id1, id2, id3; 33 REQUIRE(timeline->requestTrackInsertion(-1, id1)); 34 REQUIRE(timeline->checkConsistency()); 35 REQUIRE(timeline->getTracksCount() == 1); 36 REQUIRE(timeline->getTrackPosition(id1) == 0); 37 RESET(timMock); 38 39 REQUIRE(timeline->requestTrackInsertion(-1, id2)); 40 REQUIRE(timeline->checkConsistency()); 41 REQUIRE(timeline->getTracksCount() == 2); 42 REQUIRE(timeline->getTrackPosition(id2) == 1); 43 RESET(timMock); 44 45 REQUIRE(timeline->requestTrackInsertion(-1, id3)); 46 REQUIRE(timeline->checkConsistency()); 47 REQUIRE(timeline->getTracksCount() == 3); 48 REQUIRE(timeline->getTrackPosition(id3) == 2); 49 RESET(timMock); 50 51 int id4; 52 REQUIRE(timeline->requestTrackInsertion(1, id4)); 53 REQUIRE(timeline->checkConsistency()); 54 REQUIRE(timeline->getTracksCount() == 4); 55 REQUIRE(timeline->getTrackPosition(id1) == 0); 56 REQUIRE(timeline->getTrackPosition(id4) == 1); 57 REQUIRE(timeline->getTrackPosition(id2) == 2); 58 REQUIRE(timeline->getTrackPosition(id3) == 3); 59 RESET(timMock); 60 61 // Test deletion 62 REQUIRE(timeline->requestTrackDeletion(id3)); 63 REQUIRE(timeline->checkConsistency()); 64 REQUIRE(timeline->getTracksCount() == 3); 65 RESET(timMock); 66 67 REQUIRE(timeline->requestTrackDeletion(id1)); 68 REQUIRE(timeline->checkConsistency()); 69 REQUIRE(timeline->getTracksCount() == 2); 70 RESET(timMock); 71 72 REQUIRE(timeline->requestTrackDeletion(id4)); 73 REQUIRE(timeline->checkConsistency()); 74 REQUIRE(timeline->getTracksCount() == 1); 75 RESET(timMock); 76 77 // We are not allowed to delete the last track 78 REQUIRE_FALSE(timeline->requestTrackDeletion(id2)); 79 REQUIRE(timeline->checkConsistency()); 80 REQUIRE(timeline->getTracksCount() == 1); 81 RESET(timMock); 82 83 SECTION("Delete a track with groups") 84 { 85 int tid1, tid2; 86 REQUIRE(timeline->requestTrackInsertion(-1, tid1)); 87 REQUIRE(timeline->requestTrackInsertion(-1, tid2)); 88 REQUIRE(timeline->checkConsistency()); 89 90 QString binId = createProducer(profile_model, "red", binModel); 91 int length = 20; 92 int cid1, cid2, cid3, cid4; 93 REQUIRE(timeline->requestClipInsertion(binId, tid1, 2, cid1)); 94 REQUIRE(timeline->requestClipInsertion(binId, tid2, 0, cid2)); 95 REQUIRE(timeline->requestClipInsertion(binId, tid2, length, cid3)); 96 REQUIRE(timeline->requestClipInsertion(binId, tid2, 2 * length, cid4)); 97 REQUIRE(timeline->checkConsistency()); 98 REQUIRE(timeline->getClipsCount() == 4); 99 REQUIRE(timeline->getTracksCount() == 3); 100 101 auto g1 = std::unordered_set<int>({cid1, cid3}); 102 auto g2 = std::unordered_set<int>({cid2, cid4}); 103 auto g3 = std::unordered_set<int>({cid1, cid4}); 104 REQUIRE(timeline->requestClipsGroup(g1)); 105 REQUIRE(timeline->requestClipsGroup(g2)); 106 REQUIRE(timeline->requestClipsGroup(g3)); 107 REQUIRE(timeline->checkConsistency()); 108 109 REQUIRE(timeline->requestTrackDeletion(tid1)); 110 REQUIRE(timeline->getClipsCount() == 3); 111 REQUIRE(timeline->getTracksCount() == 2); 112 REQUIRE(timeline->checkConsistency()); 113 } 114 binModel->clean(); 115 pCore->m_projectManager = nullptr; 116 } 117 118 TEST_CASE("Basic creation/deletion of a clip", "[ClipModel]") 119 { 120 121 auto binModel = pCore->projectItemModel(); 122 std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr); 123 std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack); 124 std::shared_ptr<TimelineItemModel> timeline = TimelineItemModel::construct(&profile_model, guideModel, undoStack); 125 126 // Here we do some trickery to enable testing. 127 // We mock the project class so that the undoStack function returns our undoStack 128 129 Mock<ProjectManager> pmMock; 130 When(Method(pmMock, undoStack)).AlwaysReturn(undoStack); 131 When(Method(pmMock, cacheDir)).AlwaysReturn(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))); 132 133 ProjectManager &mocked = pmMock.get(); 134 pCore->m_projectManager = &mocked; 135 136 QString binId = createProducer(profile_model, "red", binModel); 137 QString binId2 = createProducer(profile_model, "green", binModel); 138 139 REQUIRE(timeline->getClipsCount() == 0); 140 int id1 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 141 REQUIRE(timeline->getClipsCount() == 1); 142 REQUIRE(timeline->checkConsistency()); 143 144 int id2 = ClipModel::construct(timeline, binId2, -1, PlaylistState::VideoOnly); 145 REQUIRE(timeline->getClipsCount() == 2); 146 REQUIRE(timeline->checkConsistency()); 147 148 int id3 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 149 REQUIRE(timeline->getClipsCount() == 3); 150 REQUIRE(timeline->checkConsistency()); 151 152 // Test deletion 153 REQUIRE(timeline->requestItemDeletion(id2)); 154 REQUIRE(timeline->checkConsistency()); 155 REQUIRE(timeline->getClipsCount() == 2); 156 REQUIRE(timeline->requestItemDeletion(id3)); 157 REQUIRE(timeline->checkConsistency()); 158 REQUIRE(timeline->getClipsCount() == 1); 159 REQUIRE(timeline->requestItemDeletion(id1)); 160 REQUIRE(timeline->checkConsistency()); 161 REQUIRE(timeline->getClipsCount() == 0); 162 binModel->clean(); 163 pCore->m_projectManager = nullptr; 164 } 165 166 TEST_CASE("Clip manipulation", "[ClipModel]") 167 { 168 auto binModel = pCore->projectItemModel(); 169 binModel->clean(); 170 std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr); 171 std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack); 172 173 // Here we do some trickery to enable testing. 174 // We mock the project class so that the undoStack function returns our undoStack 175 176 Mock<ProjectManager> pmMock; 177 When(Method(pmMock, undoStack)).AlwaysReturn(undoStack); 178 When(Method(pmMock, cacheDir)).AlwaysReturn(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))); 179 180 ProjectManager &mocked = pmMock.get(); 181 pCore->m_projectManager = &mocked; 182 183 // We also mock timeline object to spy few functions and mock others 184 TimelineItemModel tim(&profile_model, undoStack); 185 Mock<TimelineItemModel> timMock(tim); __anond6fdc6cc0202(...) 186 auto timeline = std::shared_ptr<TimelineItemModel>(&timMock.get(), [](...) {}); 187 TimelineItemModel::finishConstruct(timeline, guideModel); 188 189 Fake(Method(timMock, adjustAssetRange)); 190 191 // This is faked to allow to count calls 192 Fake(Method(timMock, _beginInsertRows)); 193 Fake(Method(timMock, _beginRemoveRows)); 194 Fake(Method(timMock, _endInsertRows)); 195 Fake(Method(timMock, _endRemoveRows)); 196 197 QString binId = createProducer(profile_model, "red", binModel); 198 QString binId2 = createProducer(profile_model, "blue", binModel); 199 QString binId3 = createProducer(profile_model, "green", binModel); 200 QString binId_unlimited = createProducer(profile_model, "green", binModel, 20, false); 201 202 int cid1 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 203 int tid1, tid2, tid3; 204 REQUIRE(timeline->requestTrackInsertion(-1, tid1)); 205 REQUIRE(timeline->requestTrackInsertion(-1, tid2)); 206 REQUIRE(timeline->requestTrackInsertion(-1, tid3)); 207 int cid2 = ClipModel::construct(timeline, binId2, -1, PlaylistState::VideoOnly); 208 int cid3 = ClipModel::construct(timeline, binId3, -1, PlaylistState::VideoOnly); 209 int cid4 = ClipModel::construct(timeline, binId2, -1, PlaylistState::VideoOnly); 210 int cid5 = ClipModel::construct(timeline, binId_unlimited, -1, PlaylistState::VideoOnly); 211 212 RESET(timMock); 213 214 SECTION("Endless clips can be resized both sides") 215 { 216 217 REQUIRE(timeline->checkConsistency()); 218 REQUIRE(timeline->getTrackClipsCount(tid1) == 0); 219 REQUIRE(timeline->getTrackClipsCount(tid2) == 0); 220 int l = timeline->getClipPlaytime(cid5); 221 222 // try resizing uninserted clip 223 REQUIRE(timeline->requestItemResize(cid5, l + 2, false) == l + 2); 224 REQUIRE(timeline->getClipPlaytime(cid5) == l + 2); 225 undoStack->undo(); 226 REQUIRE(timeline->getClipPlaytime(cid5) == l); 227 undoStack->redo(); 228 REQUIRE(timeline->getClipPlaytime(cid5) == l + 2); 229 undoStack->undo(); 230 REQUIRE(timeline->getClipPlaytime(cid5) == l); 231 232 REQUIRE(timeline->requestItemResize(cid5, 3 * l, true) == 3 * l); 233 REQUIRE(timeline->getClipPlaytime(cid5) == 3 * l); 234 undoStack->undo(); 235 REQUIRE(timeline->getClipPlaytime(cid5) == l); 236 undoStack->redo(); 237 REQUIRE(timeline->getClipPlaytime(cid5) == 3 * l); 238 undoStack->undo(); 239 REQUIRE(timeline->getClipPlaytime(cid5) == l); 240 241 // try resizing inserted clip 242 int pos = 10; 243 REQUIRE(timeline->requestClipMove(cid5, tid1, pos)); 244 __anond6fdc6cc0302(int s, int p) 245 auto state = [&](int s, int p) { 246 REQUIRE(timeline->checkConsistency()); 247 REQUIRE(timeline->getClipTrackId(cid5) == tid1); 248 REQUIRE(timeline->getClipPosition(cid5) == p); 249 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 250 REQUIRE(timeline->getTrackClipsCount(tid2) == 0); 251 REQUIRE(timeline->getClipPlaytime(cid5) == s); 252 }; 253 state(l, pos); 254 255 // too big 256 REQUIRE(timeline->requestItemResize(cid5, l + pos + 2, false) == -1); 257 258 REQUIRE(timeline->requestItemResize(cid5, l + 2, false) == l + 2); 259 state(l + 2, pos - 2); 260 undoStack->undo(); 261 state(l, pos); 262 undoStack->redo(); 263 state(l + 2, pos - 2); 264 undoStack->undo(); 265 state(l, pos); 266 267 REQUIRE(timeline->requestItemResize(cid5, 3 * l, true) == 3 * l); 268 state(3 * l, pos); 269 undoStack->undo(); 270 state(l, pos); 271 undoStack->redo(); 272 state(3 * l, pos); 273 undoStack->undo(); 274 state(l, pos); 275 } 276 277 SECTION("Insert a clip in a track and change track") 278 { 279 REQUIRE(timeline->checkConsistency()); 280 REQUIRE(timeline->getTrackClipsCount(tid1) == 0); 281 REQUIRE(timeline->getTrackClipsCount(tid2) == 0); 282 283 REQUIRE(timeline->getClipTrackId(cid1) == -1); 284 REQUIRE(timeline->getClipPosition(cid1) == -1); 285 286 int pos = 10; 287 REQUIRE(timeline->requestClipMove(cid1, tid1, pos)); 288 REQUIRE(timeline->checkConsistency()); 289 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 290 REQUIRE(timeline->getClipPosition(cid1) == pos); 291 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 292 REQUIRE(timeline->getTrackClipsCount(tid2) == 0); 293 // Check that the model was correctly notified 294 CHECK_INSERT(Once); 295 296 pos = 1; 297 REQUIRE(timeline->requestClipMove(cid1, tid2, pos)); 298 REQUIRE(timeline->checkConsistency()); 299 REQUIRE(timeline->getClipTrackId(cid1) == tid2); 300 REQUIRE(timeline->getClipPosition(cid1) == pos); 301 REQUIRE(timeline->getTrackClipsCount(tid2) == 1); 302 REQUIRE(timeline->getTrackClipsCount(tid1) == 0); 303 CHECK_MOVE(Once); 304 305 // Check conflicts 306 int pos2 = binModel->getClipByBinID(binId)->frameDuration(); 307 REQUIRE(timeline->requestClipMove(cid2, tid1, pos2)); 308 REQUIRE(timeline->checkConsistency()); 309 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 310 REQUIRE(timeline->getClipPosition(cid2) == pos2); 311 REQUIRE(timeline->getTrackClipsCount(tid2) == 1); 312 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 313 CHECK_INSERT(Once); 314 315 REQUIRE_FALSE(timeline->requestClipMove(cid1, tid1, pos2 + 2)); 316 REQUIRE(timeline->checkConsistency()); 317 REQUIRE(timeline->getTrackClipsCount(tid2) == 1); 318 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 319 REQUIRE(timeline->getClipTrackId(cid1) == tid2); 320 REQUIRE(timeline->getClipPosition(cid1) == pos); 321 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 322 REQUIRE(timeline->getClipPosition(cid2) == pos2); 323 CHECK_MOVE(Once); 324 325 REQUIRE_FALSE(timeline->requestClipMove(cid1, tid1, pos2 - 2)); 326 REQUIRE(timeline->checkConsistency()); 327 REQUIRE(timeline->getTrackClipsCount(tid2) == 1); 328 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 329 REQUIRE(timeline->getClipTrackId(cid1) == tid2); 330 REQUIRE(timeline->getClipPosition(cid1) == pos); 331 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 332 REQUIRE(timeline->getClipPosition(cid2) == pos2); 333 CHECK_MOVE(Once); 334 335 REQUIRE(timeline->requestClipMove(cid1, tid1, 0)); 336 REQUIRE(timeline->checkConsistency()); 337 REQUIRE(timeline->getTrackClipsCount(tid2) == 0); 338 REQUIRE(timeline->getTrackClipsCount(tid1) == 2); 339 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 340 REQUIRE(timeline->getClipPosition(cid1) == 0); 341 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 342 REQUIRE(timeline->getClipPosition(cid2) == pos2); 343 CHECK_MOVE(Once); 344 } 345 346 int length = binModel->getClipByBinID(binId)->frameDuration(); 347 SECTION("Insert consecutive clips") 348 { 349 REQUIRE(timeline->requestClipMove(cid1, tid1, 0)); 350 REQUIRE(timeline->checkConsistency()); 351 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 352 REQUIRE(timeline->getClipPosition(cid1) == 0); 353 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 354 CHECK_INSERT(Once); 355 356 REQUIRE(timeline->requestClipMove(cid2, tid1, length)); 357 REQUIRE(timeline->checkConsistency()); 358 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 359 REQUIRE(timeline->getClipPosition(cid2) == length); 360 REQUIRE(timeline->getTrackClipsCount(tid1) == 2); 361 CHECK_INSERT(Once); 362 } 363 364 SECTION("Resize orphan clip") 365 { 366 REQUIRE(timeline->getClipPlaytime(cid2) == length); 367 REQUIRE(timeline->requestItemResize(cid2, 5, true) == 5); 368 REQUIRE(timeline->checkConsistency()); 369 REQUIRE(binModel->getClipByBinID(binId)->frameDuration() == length); 370 auto inOut = std::pair<int, int>{0, 4}; 371 REQUIRE(timeline->m_allClips[cid2]->getInOut() == inOut); 372 REQUIRE(timeline->getClipPlaytime(cid2) == 5); 373 REQUIRE(timeline->requestItemResize(cid2, 10, false) == -1); 374 REQUIRE(timeline->requestItemResize(cid2, length + 1, true) == -1); 375 REQUIRE(timeline->checkConsistency()); 376 REQUIRE(timeline->getClipPlaytime(cid2) == 5); 377 REQUIRE(timeline->getClipPlaytime(cid2) == 5); 378 REQUIRE(timeline->requestItemResize(cid2, 2, false) == 2); 379 REQUIRE(timeline->checkConsistency()); 380 inOut = std::pair<int, int>{3, 4}; 381 REQUIRE(timeline->m_allClips[cid2]->getInOut() == inOut); 382 REQUIRE(timeline->getClipPlaytime(cid2) == 2); 383 REQUIRE(timeline->requestItemResize(cid2, length, true) == -1); 384 REQUIRE(timeline->checkConsistency()); 385 REQUIRE(timeline->getClipPlaytime(cid2) == 2); 386 CAPTURE(timeline->m_allClips[cid2]->m_producer->get_in()); 387 REQUIRE(timeline->requestItemResize(cid2, length - 2, true) == -1); 388 REQUIRE(timeline->checkConsistency()); 389 REQUIRE(timeline->requestItemResize(cid2, length - 3, true) == length - 3); 390 REQUIRE(timeline->checkConsistency()); 391 REQUIRE(timeline->getClipPlaytime(cid2) == length - 3); 392 } 393 394 SECTION("Resize inserted clips") 395 { 396 REQUIRE(timeline->requestClipMove(cid1, tid1, 0)); 397 REQUIRE(timeline->checkConsistency()); 398 CHECK_INSERT(Once); 399 400 REQUIRE(timeline->requestItemResize(cid1, 5, true) == 5); 401 REQUIRE(timeline->checkConsistency()); 402 REQUIRE(timeline->getClipPlaytime(cid1) == 5); 403 REQUIRE(timeline->getClipPosition(cid1) == 0); 404 CHECK_RESIZE(Once); 405 406 REQUIRE(timeline->requestClipMove(cid2, tid1, 5)); 407 REQUIRE(timeline->checkConsistency()); 408 REQUIRE(binModel->getClipByBinID(binId)->frameDuration() == length); 409 CHECK_INSERT(Once); 410 411 REQUIRE(timeline->requestItemResize(cid1, 6, true) == -1); 412 REQUIRE(timeline->requestItemResize(cid1, 6, false) == -1); 413 REQUIRE(timeline->checkConsistency()); 414 NO_OTHERS(); 415 416 REQUIRE(timeline->requestItemResize(cid2, length - 5, false) == length - 5); 417 REQUIRE(timeline->checkConsistency()); 418 REQUIRE(timeline->getClipPosition(cid2) == 10); 419 CHECK_RESIZE(Once); 420 421 REQUIRE(timeline->requestItemResize(cid1, 10, true) == 10); 422 REQUIRE(timeline->checkConsistency()); 423 REQUIRE(timeline->getTrackClipsCount(tid1) == 2); 424 CHECK_RESIZE(Once); 425 } 426 427 SECTION("Change track of resized clips") 428 { 429 // // REQUIRE(timeline->allowClipMove(cid2, tid1, 5)); 430 REQUIRE(timeline->requestClipMove(cid2, tid1, 5)); 431 REQUIRE(timeline->checkConsistency()); 432 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 433 434 // // REQUIRE(timeline->allowClipMove(cid1, tid2, 10)); 435 REQUIRE(timeline->requestClipMove(cid1, tid2, 10)); 436 REQUIRE(timeline->checkConsistency()); 437 REQUIRE(timeline->getTrackClipsCount(tid2) == 1); 438 439 REQUIRE(timeline->requestItemResize(cid1, 5, false) == 5); 440 REQUIRE(timeline->checkConsistency()); 441 442 // // REQUIRE(timeline->allowClipMove(cid1, tid1, 0)); 443 REQUIRE(timeline->requestClipMove(cid1, tid1, 0)); 444 REQUIRE(timeline->checkConsistency()); 445 REQUIRE(timeline->getTrackClipsCount(tid1) == 2); 446 REQUIRE(timeline->getTrackClipsCount(tid2) == 0); 447 } 448 449 SECTION("Clip Move") 450 { 451 REQUIRE(timeline->requestClipMove(cid2, tid1, 5)); 452 REQUIRE(timeline->checkConsistency()); 453 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 454 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 455 REQUIRE(timeline->getClipPosition(cid2) == 5); 456 457 REQUIRE(timeline->requestClipMove(cid1, tid1, 5 + length)); __anond6fdc6cc0402() 458 auto state = [&]() { 459 REQUIRE(timeline->checkConsistency()); 460 REQUIRE(timeline->getTrackClipsCount(tid1) == 2); 461 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 462 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 463 REQUIRE(timeline->getClipPosition(cid1) == 5 + length); 464 REQUIRE(timeline->getClipPosition(cid2) == 5); 465 }; 466 state(); 467 468 REQUIRE_FALSE(timeline->requestClipMove(cid1, tid1, 3 + length)); 469 state(); 470 471 REQUIRE_FALSE(timeline->requestClipMove(cid1, tid1, 0)); 472 state(); 473 474 REQUIRE(timeline->requestClipMove(cid2, tid1, 0)); __anond6fdc6cc0502() 475 auto state2 = [&]() { 476 REQUIRE(timeline->checkConsistency()); 477 REQUIRE(timeline->getTrackClipsCount(tid1) == 2); 478 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 479 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 480 REQUIRE(timeline->getClipPosition(cid1) == 5 + length); 481 REQUIRE(timeline->getClipPosition(cid2) == 0); 482 }; 483 state2(); 484 485 REQUIRE_FALSE(timeline->requestClipMove(cid1, tid1, 0)); 486 state2(); 487 488 REQUIRE_FALSE(timeline->requestClipMove(cid1, tid1, length - 5)); 489 state2(); 490 491 REQUIRE(timeline->requestClipMove(cid1, tid1, length)); 492 REQUIRE(timeline->checkConsistency()); 493 REQUIRE(timeline->getTrackClipsCount(tid1) == 2); 494 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 495 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 496 REQUIRE(timeline->getClipPosition(cid1) == length); 497 REQUIRE(timeline->getClipPosition(cid2) == 0); 498 499 REQUIRE(timeline->requestItemResize(cid2, length - 5, true) == length - 5); 500 REQUIRE(timeline->checkConsistency()); 501 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 502 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 503 REQUIRE(timeline->getClipPosition(cid1) == length); 504 REQUIRE(timeline->getClipPosition(cid2) == 0); 505 506 REQUIRE(timeline->requestClipMove(cid1, tid1, length - 5)); 507 REQUIRE(timeline->checkConsistency()); 508 REQUIRE(timeline->getTrackClipsCount(tid1) == 2); 509 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 510 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 511 REQUIRE(timeline->getClipPosition(cid1) == length - 5); 512 REQUIRE(timeline->getClipPosition(cid2) == 0); 513 514 REQUIRE(timeline->requestItemResize(cid2, length - 10, false) == length - 10); 515 REQUIRE(timeline->checkConsistency()); 516 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 517 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 518 REQUIRE(timeline->getClipPosition(cid1) == length - 5); 519 REQUIRE(timeline->getClipPosition(cid2) == 5); 520 521 REQUIRE_FALSE(timeline->requestClipMove(cid1, tid1, 0)); 522 REQUIRE(timeline->checkConsistency()); 523 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 524 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 525 REQUIRE(timeline->getClipPosition(cid1) == length - 5); 526 REQUIRE(timeline->getClipPosition(cid2) == 5); 527 528 REQUIRE(timeline->requestClipMove(cid2, tid1, 0)); 529 REQUIRE(timeline->checkConsistency()); 530 REQUIRE(timeline->getTrackClipsCount(tid1) == 2); 531 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 532 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 533 REQUIRE(timeline->getClipPosition(cid1) == length - 5); 534 REQUIRE(timeline->getClipPosition(cid2) == 0); 535 } 536 537 SECTION("Move and resize") 538 { 539 REQUIRE(timeline->requestClipMove(cid1, tid1, 0)); 540 REQUIRE(timeline->requestItemResize(cid1, length - 2, false) == length - 2); 541 REQUIRE(timeline->requestClipMove(cid1, tid1, 0)); __anond6fdc6cc0602() 542 auto state = [&]() { 543 REQUIRE(timeline->checkConsistency()); 544 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 545 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 546 REQUIRE(timeline->getClipPosition(cid1) == 0); 547 REQUIRE(timeline->getClipPlaytime(cid1) == length - 2); 548 }; 549 state(); 550 551 // try to resize past the left end 552 REQUIRE(timeline->requestItemResize(cid1, length, false) == -1); 553 state(); 554 555 REQUIRE(timeline->requestItemResize(cid1, length - 4, true) == length - 4); 556 REQUIRE(timeline->requestClipMove(cid2, tid1, length - 4 + 1)); 557 REQUIRE(timeline->requestItemResize(cid2, length - 2, false) == length - 2); 558 REQUIRE(timeline->requestClipMove(cid2, tid1, length - 4 + 1)); __anond6fdc6cc0702() 559 auto state2 = [&]() { 560 REQUIRE(timeline->checkConsistency()); 561 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 562 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 563 REQUIRE(timeline->getTrackClipsCount(tid1) == 2); 564 REQUIRE(timeline->getClipPosition(cid1) == 0); 565 REQUIRE(timeline->getClipPlaytime(cid1) == length - 4); 566 REQUIRE(timeline->getClipPosition(cid2) == length - 4 + 1); 567 REQUIRE(timeline->getClipPlaytime(cid2) == length - 2); 568 }; 569 state2(); 570 571 // the gap between the two clips is 1 frame, we try to resize them by 2 frames 572 // It will only be resized by one frame 573 REQUIRE(timeline->requestItemResize(cid1, length - 2, true) == length - 3); 574 undoStack->undo(); 575 state2(); 576 // Resize a clip over another clip will resize it to fill the gap 577 REQUIRE(timeline->requestItemResize(cid2, length, false) == length - 1); 578 undoStack->undo(); 579 state2(); 580 581 REQUIRE(timeline->requestClipMove(cid2, tid1, length - 4)); __anond6fdc6cc0802() 582 auto state3 = [&]() { 583 REQUIRE(timeline->checkConsistency()); 584 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 585 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 586 REQUIRE(timeline->getTrackClipsCount(tid1) == 2); 587 REQUIRE(timeline->getClipPosition(cid1) == 0); 588 REQUIRE(timeline->getClipPlaytime(cid1) == length - 4); 589 REQUIRE(timeline->getClipPosition(cid2) == length - 4); 590 REQUIRE(timeline->getClipPlaytime(cid2) == length - 2); 591 }; 592 state3(); 593 594 // Now the gap is 0 frames, the resize should still fail 595 REQUIRE(timeline->requestItemResize(cid1, length - 2, true) == -1); 596 state3(); 597 REQUIRE(timeline->requestItemResize(cid2, length, false) == -1); 598 state3(); 599 600 // We move cid1 out of the way 601 REQUIRE(timeline->requestClipMove(cid1, tid2, 0)); 602 // now resize should work 603 REQUIRE(timeline->requestItemResize(cid1, length - 2, true) == length - 2); 604 REQUIRE(timeline->requestItemResize(cid2, length, false) == length); 605 REQUIRE(timeline->checkConsistency()); 606 } 607 608 SECTION("Group and selection") 609 { 610 REQUIRE(timeline->requestClipMove(cid1, tid1, 0)); 611 REQUIRE(timeline->requestClipMove(cid2, tid1, length + 3)); 612 REQUIRE(timeline->requestClipMove(cid3, tid1, 2 * length + 5)); __anond6fdc6cc0902() 613 auto pos_state = [&]() { 614 REQUIRE(timeline->checkConsistency()); 615 REQUIRE(timeline->getTrackClipsCount(tid1) == 3); 616 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 617 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 618 REQUIRE(timeline->getClipTrackId(cid3) == tid1); 619 REQUIRE(timeline->getClipPosition(cid1) == 0); 620 REQUIRE(timeline->getClipPosition(cid2) == length + 3); 621 REQUIRE(timeline->getClipPosition(cid3) == 2 * length + 5); 622 }; __anond6fdc6cc0a02() 623 auto state0 = [&]() { 624 pos_state(); 625 REQUIRE_FALSE(timeline->m_groups->isInGroup(cid1)); 626 REQUIRE_FALSE(timeline->m_groups->isInGroup(cid2)); 627 REQUIRE_FALSE(timeline->m_groups->isInGroup(cid3)); 628 }; 629 state0(); 630 631 REQUIRE(timeline->requestClipsGroup({cid1, cid2})); __anond6fdc6cc0b02() 632 auto state = [&]() { 633 pos_state(); 634 REQUIRE_FALSE(timeline->m_groups->isInGroup(cid3)); 635 REQUIRE(timeline->m_groups->isInGroup(cid1)); 636 int gid = timeline->m_groups->getRootId(cid1); 637 REQUIRE(timeline->m_groups->getLeaves(gid) == std::unordered_set<int>{cid1, cid2}); 638 }; 639 state(); 640 641 // undo/redo should work fine 642 undoStack->undo(); 643 state0(); 644 undoStack->redo(); 645 state(); 646 647 // Tricky case, we do a non-trivial selection before undoing 648 REQUIRE(timeline->requestSetSelection({cid1, cid3})); 649 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3}); 650 undoStack->undo(); 651 state0(); 652 REQUIRE(timeline->requestSetSelection({cid1, cid3})); 653 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid3}); 654 undoStack->redo(); 655 state(); 656 657 // same thing, but when ungrouping manually 658 REQUIRE(timeline->requestSetSelection({cid1, cid3})); 659 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3}); 660 REQUIRE(timeline->requestClipUngroup(cid1)); 661 state0(); 662 663 // normal undo/redo 664 undoStack->undo(); 665 state(); 666 undoStack->redo(); 667 state0(); 668 669 // undo/redo mixed with selections 670 REQUIRE(timeline->requestSetSelection({cid1, cid3})); 671 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid3}); 672 undoStack->undo(); 673 state(); 674 REQUIRE(timeline->requestSetSelection({cid1, cid3})); 675 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3}); 676 undoStack->redo(); 677 state0(); 678 } 679 680 SECTION("Group move") 681 { 682 REQUIRE(timeline->requestClipMove(cid1, tid1, 0)); 683 REQUIRE(timeline->requestClipMove(cid2, tid1, length + 3)); 684 REQUIRE(timeline->requestClipMove(cid3, tid1, 2 * length + 5)); 685 REQUIRE(timeline->requestClipMove(cid4, tid2, 4)); 686 687 REQUIRE(timeline->checkConsistency()); 688 REQUIRE(timeline->getTrackClipsCount(tid1) == 3); 689 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 690 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 691 REQUIRE(timeline->getClipTrackId(cid3) == tid1); 692 REQUIRE(timeline->getClipTrackId(cid4) == tid2); 693 REQUIRE(timeline->getClipPosition(cid1) == 0); 694 REQUIRE(timeline->getClipPosition(cid2) == length + 3); 695 REQUIRE(timeline->getClipPosition(cid3) == 2 * length + 5); 696 REQUIRE(timeline->getClipPosition(cid4) == 4); 697 698 // check that move is possible without groups 699 REQUIRE(timeline->requestClipMove(cid3, tid1, 2 * length + 3)); 700 REQUIRE(timeline->checkConsistency()); 701 undoStack->undo(); 702 REQUIRE(timeline->checkConsistency()); 703 // check that move is possible without groups 704 REQUIRE(timeline->requestClipMove(cid4, tid2, 9)); 705 REQUIRE(timeline->checkConsistency()); 706 undoStack->undo(); 707 REQUIRE(timeline->checkConsistency()); 708 __anond6fdc6cc0c02() 709 auto state = [&]() { 710 REQUIRE(timeline->checkConsistency()); 711 REQUIRE(timeline->getTrackClipsCount(tid1) == 3); 712 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 713 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 714 REQUIRE(timeline->getClipTrackId(cid3) == tid1); 715 REQUIRE(timeline->getClipTrackId(cid4) == tid2); 716 REQUIRE(timeline->getClipPosition(cid1) == 0); 717 REQUIRE(timeline->getClipPosition(cid2) == length + 3); 718 REQUIRE(timeline->getClipPosition(cid3) == 2 * length + 5); 719 REQUIRE(timeline->getClipPosition(cid4) == 4); 720 }; 721 state(); 722 723 // grouping 724 REQUIRE(timeline->requestClipsGroup({cid1, cid3})); 725 REQUIRE(timeline->requestClipsGroup({cid1, cid4})); 726 727 // move left is now forbidden, because clip1 is at position 0 728 REQUIRE_FALSE(timeline->requestClipMove(cid3, tid1, 2 * length + 3)); 729 state(); 730 731 // this move is impossible, because clip1 runs into clip2 732 REQUIRE_FALSE(timeline->requestClipMove(cid4, tid2, 9)); 733 state(); 734 735 // this move is possible 736 REQUIRE(timeline->requestClipMove(cid3, tid1, 2 * length + 8)); __anond6fdc6cc0d02() 737 auto state1 = [&]() { 738 REQUIRE(timeline->checkConsistency()); 739 REQUIRE(timeline->getTrackClipsCount(tid1) == 3); 740 REQUIRE(timeline->getTrackClipsCount(tid2) == 1); 741 REQUIRE(timeline->getTrackClipsCount(tid3) == 0); 742 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 743 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 744 REQUIRE(timeline->getClipTrackId(cid3) == tid1); 745 REQUIRE(timeline->getClipTrackId(cid4) == tid2); 746 REQUIRE(timeline->getClipPosition(cid1) == 3); 747 REQUIRE(timeline->getClipPosition(cid2) == length + 3); 748 REQUIRE(timeline->getClipPosition(cid3) == 2 * length + 8); 749 REQUIRE(timeline->getClipPosition(cid4) == 7); 750 }; 751 state1(); 752 753 // this move is possible 754 REQUIRE(timeline->requestClipMove(cid1, tid2, 8)); __anond6fdc6cc0e02() 755 auto state2 = [&]() { 756 REQUIRE(timeline->checkConsistency()); 757 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 758 REQUIRE(timeline->getTrackClipsCount(tid2) == 2); 759 REQUIRE(timeline->getTrackClipsCount(tid3) == 1); 760 REQUIRE(timeline->getClipTrackId(cid1) == tid2); 761 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 762 REQUIRE(timeline->getClipTrackId(cid3) == tid2); 763 REQUIRE(timeline->getClipTrackId(cid4) == tid3); 764 REQUIRE(timeline->getClipPosition(cid1) == 8); 765 REQUIRE(timeline->getClipPosition(cid2) == length + 3); 766 REQUIRE(timeline->getClipPosition(cid3) == 2 * length + 5 + 8); 767 REQUIRE(timeline->getClipPosition(cid4) == 4 + 8); 768 }; 769 state2(); 770 771 undoStack->undo(); 772 state1(); 773 774 undoStack->redo(); 775 state2(); 776 777 REQUIRE(timeline->requestClipMove(cid1, tid1, 3)); 778 state1(); 779 } 780 781 SECTION("Group move consecutive clips") 782 { 783 REQUIRE(timeline->requestClipMove(cid1, tid1, 7)); 784 REQUIRE(timeline->requestClipMove(cid2, tid1, 7 + length)); 785 REQUIRE(timeline->requestClipMove(cid3, tid1, 7 + 2 * length)); 786 REQUIRE(timeline->requestClipMove(cid4, tid1, 7 + 3 * length)); 787 REQUIRE(timeline->requestClipsGroup({cid1, cid2, cid3, cid4})); 788 __anond6fdc6cc0f02(int tid, int start) 789 auto state = [&](int tid, int start) { 790 REQUIRE(timeline->checkConsistency()); 791 REQUIRE(timeline->getTrackClipsCount(tid) == 4); 792 int i = 0; 793 for (int cid : std::vector<int>({cid1, cid2, cid3, cid4})) { 794 REQUIRE(timeline->getClipTrackId(cid) == tid); 795 REQUIRE(timeline->getClipPosition(cid) == start + i * length); 796 REQUIRE(timeline->getClipPlaytime(cid) == length); 797 i++; 798 } 799 }; 800 state(tid1, 7); 801 __anond6fdc6cc1002(int target, int tid, int oldTid) 802 auto check_undo = [&](int target, int tid, int oldTid) { 803 state(tid, target); 804 undoStack->undo(); 805 state(oldTid, 7); 806 undoStack->redo(); 807 state(tid, target); 808 undoStack->undo(); 809 state(oldTid, 7); 810 }; 811 812 REQUIRE(timeline->requestClipMove(cid1, tid1, 6)); 813 qDebug() << "state1"; 814 state(tid1, 6); 815 undoStack->undo(); 816 state(tid1, 7); 817 undoStack->redo(); 818 state(tid1, 6); 819 REQUIRE(timeline->requestClipMove(cid1, tid1, 0)); 820 qDebug() << "state2"; 821 state(tid1, 0); 822 undoStack->undo(); 823 state(tid1, 6); 824 undoStack->redo(); 825 state(tid1, 0); 826 undoStack->undo(); 827 state(tid1, 6); 828 undoStack->undo(); 829 state(tid1, 7); 830 831 REQUIRE(timeline->requestClipMove(cid3, tid1, 1 + 2 * length)); 832 qDebug() << "state3"; 833 check_undo(1, tid1, tid1); 834 835 REQUIRE(timeline->requestClipMove(cid4, tid1, 4 + 3 * length)); 836 qDebug() << "state4"; 837 check_undo(4, tid1, tid1); 838 839 REQUIRE(timeline->requestClipMove(cid4, tid1, 11 + 3 * length)); 840 qDebug() << "state5"; 841 check_undo(11, tid1, tid1); 842 843 REQUIRE(timeline->requestClipMove(cid2, tid1, 13 + length)); 844 qDebug() << "state6"; 845 check_undo(13, tid1, tid1); 846 847 REQUIRE(timeline->requestClipMove(cid1, tid1, 20)); 848 qDebug() << "state7"; 849 check_undo(20, tid1, tid1); 850 851 REQUIRE(timeline->requestClipMove(cid4, tid1, 7 + 4 * length)); 852 qDebug() << "state8"; 853 check_undo(length + 7, tid1, tid1); 854 855 REQUIRE(timeline->requestClipMove(cid2, tid1, 7 + 2 * length)); 856 qDebug() << "state9"; 857 check_undo(length + 7, tid1, tid1); 858 859 REQUIRE(timeline->requestClipMove(cid1, tid1, 7 + length)); 860 qDebug() << "state10"; 861 check_undo(length + 7, tid1, tid1); 862 863 REQUIRE(timeline->requestClipMove(cid2, tid2, 8 + length)); 864 qDebug() << "state11"; 865 check_undo(8, tid2, tid1); 866 } 867 868 SECTION("Group move to unavailable track") 869 { 870 REQUIRE(timeline->requestClipMove(cid1, tid1, 10)); 871 REQUIRE(timeline->requestClipMove(cid2, tid2, 12)); 872 REQUIRE(timeline->requestClipsGroup({cid1, cid2})); __anond6fdc6cc1102() 873 auto state = [&]() { 874 REQUIRE(timeline->checkConsistency()); 875 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 876 REQUIRE(timeline->getTrackClipsCount(tid2) == 1); 877 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 878 REQUIRE(timeline->getClipTrackId(cid2) == tid2); 879 }; 880 state(); 881 882 // Moving clips on an unavailable track will do a same track move 883 REQUIRE(timeline->requestClipMove(cid2, tid1, 10)); 884 REQUIRE(timeline->getClipPosition(cid1) == 8); 885 REQUIRE(timeline->getClipPosition(cid2) == 10); 886 state(); 887 REQUIRE(timeline->requestClipMove(cid2, tid1, 100)); 888 REQUIRE(timeline->getClipPosition(cid1) == 98); 889 REQUIRE(timeline->getClipPosition(cid2) == 100); 890 state(); 891 REQUIRE(timeline->requestClipMove(cid1, tid3, 100)); 892 REQUIRE(timeline->getClipPosition(cid1) == 100); 893 REQUIRE(timeline->getClipPosition(cid2) == 102); 894 state(); 895 } 896 897 SECTION("Group move with non-consecutive track ids") 898 { 899 int tid5 = TrackModel::construct(timeline); 900 int cid6 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 901 Q_UNUSED(cid6); 902 int tid6 = TrackModel::construct(timeline); 903 REQUIRE(tid5 + 1 != tid6); 904 905 REQUIRE(timeline->requestClipMove(cid1, tid5, 10)); 906 REQUIRE(timeline->requestClipMove(cid2, tid5, length + 10)); 907 REQUIRE(timeline->requestClipsGroup({cid1, cid2})); __anond6fdc6cc1202(int t) 908 auto state = [&](int t) { 909 REQUIRE(timeline->checkConsistency()); 910 REQUIRE(timeline->getTrackClipsCount(t) == 2); 911 REQUIRE(timeline->getClipTrackId(cid1) == t); 912 REQUIRE(timeline->getClipTrackId(cid2) == t); 913 REQUIRE(timeline->getClipPosition(cid1) == 10); 914 REQUIRE(timeline->getClipPosition(cid2) == 10 + length); 915 }; 916 state(tid5); 917 REQUIRE(timeline->requestClipMove(cid1, tid6, 10)); 918 state(tid6); 919 } 920 921 SECTION("Creation and movement of AV groups") 922 { 923 int tid6b = TrackModel::construct(timeline, -1, -1, QString(), true); 924 int tid6 = TrackModel::construct(timeline, -1, -1, QString(), true); 925 int tid5 = TrackModel::construct(timeline); 926 int tid5b = TrackModel::construct(timeline); __anond6fdc6cc1302() 927 auto state0 = [&]() { 928 REQUIRE(timeline->checkConsistency()); 929 REQUIRE(timeline->getTrackClipsCount(tid5) == 0); 930 REQUIRE(timeline->getTrackClipsCount(tid6) == 0); 931 }; 932 state0(); 933 QString binId3 = createProducerWithSound(profile_model, binModel); 934 935 int cid6 = -1; 936 // Setup insert stream data 937 QMap <int, QString>audioInfo; 938 audioInfo.insert(1,QStringLiteral("stream1")); 939 timeline->m_binAudioTargets = audioInfo; 940 REQUIRE(timeline->requestClipInsertion(binId3, tid5, 3, cid6, true, true, false)); 941 int cid7 = timeline->m_groups->getSplitPartner(cid6); 942 __anond6fdc6cc1402() 943 auto check_group = [&]() { 944 // we check that the av group was correctly created 945 REQUIRE(timeline->getGroupElements(cid6) == std::unordered_set<int>({cid6, cid7})); 946 int g1 = timeline->m_groups->getDirectAncestor(cid6); 947 REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({cid6, cid7})); 948 REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit); 949 }; 950 __anond6fdc6cc1502(int pos) 951 auto state = [&](int pos) { 952 REQUIRE(timeline->checkConsistency()); 953 REQUIRE(timeline->getTrackClipsCount(tid5) == 1); 954 REQUIRE(timeline->getTrackClipsCount(tid6) == 1); 955 REQUIRE(timeline->getClipTrackId(cid6) == tid5); 956 REQUIRE(timeline->getClipTrackId(cid7) == tid6); 957 REQUIRE(timeline->getClipPosition(cid6) == pos); 958 REQUIRE(timeline->getClipPosition(cid7) == pos); 959 REQUIRE(timeline->getClipPtr(cid6)->clipState() == PlaylistState::VideoOnly); 960 REQUIRE(timeline->getClipPtr(cid7)->clipState() == PlaylistState::AudioOnly); 961 check_group(); 962 }; 963 state(3); 964 undoStack->undo(); 965 state0(); 966 undoStack->redo(); 967 state(3); 968 969 // test deletion + undo after selection 970 REQUIRE(timeline->requestSetSelection({cid6})); 971 REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid6, cid7}); 972 973 REQUIRE(timeline->requestItemDeletion(cid6, true)); 974 state0(); 975 undoStack->undo(); 976 state(3); 977 undoStack->redo(); 978 state0(); 979 undoStack->undo(); 980 state(3); 981 982 // simple translation on the right 983 REQUIRE(timeline->requestClipMove(cid6, tid5, 10, true, true, true)); 984 985 state(10); 986 undoStack->undo(); 987 state(3); 988 undoStack->redo(); 989 state(10); 990 991 // simple translation on the left, moving the audio clip this time 992 REQUIRE(timeline->requestClipMove(cid7, tid6, 1, true, true, true)); 993 state(1); 994 undoStack->undo(); 995 state(10); 996 undoStack->redo(); 997 state(1); 998 999 // change track, moving video 1000 REQUIRE(timeline->requestClipMove(cid6, tid5b, 7, true, true, true)); __anond6fdc6cc1602(int pos) 1001 auto state2 = [&](int pos) { 1002 REQUIRE(timeline->checkConsistency()); 1003 REQUIRE(timeline->getTrackClipsCount(tid5b) == 1); 1004 REQUIRE(timeline->getTrackClipsCount(tid6b) == 1); 1005 REQUIRE(timeline->getClipTrackId(cid6) == tid5b); 1006 REQUIRE(timeline->getClipTrackId(cid7) == tid6b); 1007 REQUIRE(timeline->getClipPosition(cid6) == pos); 1008 REQUIRE(timeline->getClipPosition(cid7) == pos); 1009 REQUIRE(timeline->getClipPtr(cid6)->clipState() == PlaylistState::VideoOnly); 1010 REQUIRE(timeline->getClipPtr(cid7)->clipState() == PlaylistState::AudioOnly); 1011 check_group(); 1012 }; 1013 state2(7); 1014 undoStack->undo(); 1015 state(1); 1016 undoStack->redo(); 1017 state2(7); 1018 1019 // change track, moving audio 1020 REQUIRE(timeline->requestClipMove(cid7, tid6b, 2, true, true, true)); 1021 state2(2); 1022 undoStack->undo(); 1023 state2(7); 1024 undoStack->redo(); 1025 state2(2); 1026 1027 undoStack->undo(); 1028 undoStack->undo(); 1029 state(1); 1030 } 1031 1032 SECTION("Clip clone") 1033 { 1034 int cid6 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 1035 int l = timeline->getClipPlaytime(cid6); 1036 REQUIRE(timeline->requestItemResize(cid6, l - 3, true, true, -1) == l - 3); 1037 REQUIRE(timeline->requestItemResize(cid6, l - 7, false, true, -1) == l - 7); 1038 1039 int newId; 1040 __anond6fdc6cc1702() 1041 std::function<bool(void)> undo = []() { return true; }; __anond6fdc6cc1802() 1042 std::function<bool(void)> redo = []() { return true; }; 1043 REQUIRE(TimelineFunctions::cloneClip(timeline, cid6, newId, PlaylistState::VideoOnly, undo, redo)); 1044 REQUIRE(timeline->m_allClips[cid6]->binId() == timeline->m_allClips[newId]->binId()); 1045 // TODO check effects 1046 } 1047 binModel->clean(); 1048 pCore->m_projectManager = nullptr; 1049 } 1050 1051 TEST_CASE("Check id unicity", "[ClipModel]") 1052 { 1053 auto binModel = pCore->projectItemModel(); 1054 binModel->clean(); 1055 std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr); 1056 std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack); 1057 1058 // Here we do some trickery to enable testing. 1059 // We mock the project class so that the undoStack function returns our undoStack 1060 1061 Mock<ProjectManager> pmMock; 1062 When(Method(pmMock, undoStack)).AlwaysReturn(undoStack); 1063 When(Method(pmMock, cacheDir)).AlwaysReturn(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))); 1064 1065 ProjectManager &mocked = pmMock.get(); 1066 pCore->m_projectManager = &mocked; 1067 1068 // We also mock timeline object to spy few functions and mock others 1069 TimelineItemModel tim(&profile_model, undoStack); 1070 Mock<TimelineItemModel> timMock(tim); __anond6fdc6cc1902(...) 1071 auto timeline = std::shared_ptr<TimelineItemModel>(&timMock.get(), [](...) {}); 1072 TimelineItemModel::finishConstruct(timeline, guideModel); 1073 1074 RESET(timMock); 1075 1076 QString binId = createProducer(profile_model, "red", binModel); 1077 1078 std::vector<int> track_ids; 1079 std::unordered_set<int> all_ids; 1080 1081 std::bernoulli_distribution coin(0.5); 1082 1083 const int nbr = 20; 1084 1085 for (int i = 0; i < nbr; i++) { 1086 if (coin(g)) { 1087 int tid = TrackModel::construct(timeline); 1088 REQUIRE(all_ids.count(tid) == 0); 1089 all_ids.insert(tid); 1090 track_ids.push_back(tid); 1091 REQUIRE(timeline->getTracksCount() == track_ids.size()); 1092 } else { 1093 int cid = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 1094 REQUIRE(all_ids.count(cid) == 0); 1095 all_ids.insert(cid); 1096 REQUIRE(timeline->getClipsCount() == all_ids.size() - track_ids.size()); 1097 } 1098 } 1099 1100 REQUIRE(timeline->checkConsistency()); 1101 REQUIRE(all_ids.size() == nbr); 1102 REQUIRE(all_ids.size() != track_ids.size()); 1103 binModel->clean(); 1104 pCore->m_projectManager = nullptr; 1105 } 1106 1107 TEST_CASE("Undo and Redo", "[ClipModel]") 1108 { 1109 auto binModel = pCore->projectItemModel(); 1110 binModel->clean(); 1111 std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr); 1112 std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack); 1113 1114 // Here we do some trickery to enable testing. 1115 // We mock the project class so that the undoStack function returns our undoStack 1116 1117 Mock<ProjectManager> pmMock; 1118 When(Method(pmMock, undoStack)).AlwaysReturn(undoStack); 1119 When(Method(pmMock, cacheDir)).AlwaysReturn(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))); 1120 1121 ProjectManager &mocked = pmMock.get(); 1122 pCore->m_projectManager = &mocked; 1123 1124 // We also mock timeline object to spy few functions and mock others 1125 TimelineItemModel tim(&profile_model, undoStack); 1126 Mock<TimelineItemModel> timMock(tim); __anond6fdc6cc1a02(...) 1127 auto timeline = std::shared_ptr<TimelineItemModel>(&timMock.get(), [](...) {}); 1128 TimelineItemModel::finishConstruct(timeline, guideModel); 1129 1130 RESET(timMock); 1131 1132 QString binId = createProducer(profile_model, "red", binModel); 1133 QString binId2 = createProducer(profile_model, "blue", binModel); 1134 1135 int cid1 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 1136 int tid1 = TrackModel::construct(timeline); 1137 int tid2 = TrackModel::construct(timeline); 1138 int cid2 = ClipModel::construct(timeline, binId2, -1, PlaylistState::VideoOnly); 1139 1140 int length = 20; 1141 int nclips = timeline->m_allClips.size(); 1142 1143 SECTION("requestCreateClip") 1144 { 1145 // an invalid clip id shouldn't get created 1146 { 1147 int temp; __anond6fdc6cc1b02() 1148 Fun undo = []() { return true; }; __anond6fdc6cc1c02() 1149 Fun redo = []() { return true; }; 1150 REQUIRE_FALSE(timeline->requestClipCreation("impossible bin id", temp, PlaylistState::VideoOnly, 1, 1., false, undo, redo)); 1151 } 1152 __anond6fdc6cc1d02() 1153 auto state0 = [&]() { 1154 REQUIRE(timeline->checkConsistency()); 1155 REQUIRE(timeline->m_allClips.size() == nclips); 1156 }; 1157 state0(); 1158 1159 QString binId3 = createProducer(profile_model, "green", binModel); 1160 int cid3; 1161 { __anond6fdc6cc1e02() 1162 Fun undo = []() { return true; }; __anond6fdc6cc1f02() 1163 Fun redo = []() { return true; }; 1164 REQUIRE(timeline->requestClipCreation(binId3, cid3, PlaylistState::VideoOnly, 1, 1., false, undo, redo)); 1165 pCore->pushUndo(undo, redo, QString()); 1166 } 1167 __anond6fdc6cc2002() 1168 auto state1 = [&]() { 1169 REQUIRE(timeline->checkConsistency()); 1170 REQUIRE(timeline->m_allClips.size() == nclips + 1); 1171 REQUIRE(timeline->getClipPlaytime(cid3) == length); 1172 REQUIRE(timeline->getClipTrackId(cid3) == -1); 1173 }; 1174 state1(); 1175 1176 QString binId4 = binId3 + "/1/10"; 1177 int cid4; 1178 { __anond6fdc6cc2102() 1179 Fun undo = []() { return true; }; __anond6fdc6cc2202() 1180 Fun redo = []() { return true; }; 1181 REQUIRE(timeline->requestClipCreation(binId4, cid4, PlaylistState::VideoOnly, 1, 1., false, undo, redo)); 1182 pCore->pushUndo(undo, redo, QString()); 1183 } 1184 __anond6fdc6cc2302() 1185 auto state2 = [&]() { 1186 REQUIRE(timeline->checkConsistency()); 1187 REQUIRE(timeline->m_allClips.size() == nclips + 2); 1188 REQUIRE(timeline->getClipPlaytime(cid4) == 10); 1189 REQUIRE(timeline->getClipTrackId(cid4) == -1); 1190 auto inOut = std::pair<int, int>({1, 10}); 1191 REQUIRE(timeline->m_allClips.at(cid4)->getInOut() == inOut); 1192 REQUIRE(timeline->getClipPlaytime(cid3) == length); 1193 REQUIRE(timeline->getClipTrackId(cid3) == -1); 1194 }; 1195 state2(); 1196 undoStack->undo(); 1197 state1(); 1198 undoStack->undo(); 1199 state0(); 1200 undoStack->redo(); 1201 state1(); 1202 undoStack->redo(); 1203 state2(); 1204 } 1205 1206 SECTION("requestInsertClip") 1207 { __anond6fdc6cc2402() 1208 auto state0 = [&]() { 1209 REQUIRE(timeline->checkConsistency()); 1210 REQUIRE(timeline->m_allClips.size() == nclips); 1211 }; 1212 state0(); 1213 1214 QString binId3 = createProducer(profile_model, "green", binModel); 1215 int cid3; 1216 REQUIRE(timeline->requestClipInsertion(binId3, tid1, 12, cid3, true)); 1217 __anond6fdc6cc2502() 1218 auto state1 = [&]() { 1219 REQUIRE(timeline->checkConsistency()); 1220 REQUIRE(timeline->m_allClips.size() == nclips + 1); 1221 REQUIRE(timeline->getClipPlaytime(cid3) == length); 1222 REQUIRE(timeline->getClipTrackId(cid3) == tid1); 1223 REQUIRE(timeline->getClipPosition(cid3) == 12); 1224 }; 1225 state1(); 1226 1227 QString binId4 = binId3 + "/1/10"; 1228 int cid4; 1229 REQUIRE(timeline->requestClipInsertion(binId4, tid2, 17, cid4, true)); 1230 __anond6fdc6cc2602() 1231 auto state2 = [&]() { 1232 REQUIRE(timeline->checkConsistency()); 1233 REQUIRE(timeline->m_allClips.size() == nclips + 2); 1234 REQUIRE(timeline->getClipPlaytime(cid4) == 10); 1235 REQUIRE(timeline->getClipTrackId(cid4) == tid2); 1236 REQUIRE(timeline->getClipPosition(cid4) == 17); 1237 auto inOut = std::pair<int, int>({1, 10}); 1238 REQUIRE(timeline->m_allClips.at(cid4)->getInOut() == inOut); 1239 REQUIRE(timeline->getClipPlaytime(cid3) == length); 1240 REQUIRE(timeline->getClipTrackId(cid3) == tid1); 1241 REQUIRE(timeline->getClipPosition(cid3) == 12); 1242 }; 1243 state2(); 1244 undoStack->undo(); 1245 state1(); 1246 undoStack->undo(); 1247 state0(); 1248 undoStack->redo(); 1249 state1(); 1250 undoStack->redo(); 1251 state2(); 1252 } 1253 int init_index = undoStack->index(); 1254 1255 SECTION("Basic move undo") 1256 { 1257 REQUIRE(timeline->requestClipMove(cid1, tid1, 5)); 1258 REQUIRE(timeline->checkConsistency()); 1259 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 1260 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1261 REQUIRE(timeline->getClipPosition(cid1) == 5); 1262 REQUIRE(undoStack->index() == init_index + 1); 1263 CHECK_INSERT(Once); 1264 1265 REQUIRE(timeline->requestClipMove(cid1, tid1, 0)); 1266 REQUIRE(timeline->checkConsistency()); 1267 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 1268 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1269 REQUIRE(timeline->getClipPosition(cid1) == 0); 1270 REQUIRE(undoStack->index() == init_index + 2); 1271 // Move on same track does not trigger insert/remove row 1272 CHECK_MOVE(0); 1273 1274 undoStack->undo(); 1275 REQUIRE(timeline->checkConsistency()); 1276 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 1277 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1278 REQUIRE(timeline->getClipPosition(cid1) == 5); 1279 REQUIRE(undoStack->index() == init_index + 1); 1280 CHECK_MOVE(0); 1281 1282 undoStack->redo(); 1283 REQUIRE(timeline->checkConsistency()); 1284 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 1285 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1286 REQUIRE(timeline->getClipPosition(cid1) == 0); 1287 REQUIRE(undoStack->index() == init_index + 2); 1288 CHECK_MOVE(0); 1289 1290 undoStack->undo(); 1291 REQUIRE(timeline->checkConsistency()); 1292 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 1293 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1294 REQUIRE(timeline->getClipPosition(cid1) == 5); 1295 REQUIRE(undoStack->index() == init_index + 1); 1296 CHECK_MOVE(0); 1297 1298 REQUIRE(timeline->requestClipMove(cid1, tid1, 2 * length)); 1299 REQUIRE(timeline->checkConsistency()); 1300 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 1301 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1302 REQUIRE(timeline->getClipPosition(cid1) == 2 * length); 1303 REQUIRE(undoStack->index() == init_index + 2); 1304 CHECK_MOVE(0); 1305 1306 undoStack->undo(); 1307 REQUIRE(timeline->checkConsistency()); 1308 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 1309 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1310 REQUIRE(timeline->getClipPosition(cid1) == 5); 1311 REQUIRE(undoStack->index() == init_index + 1); 1312 CHECK_MOVE(0); 1313 1314 undoStack->redo(); 1315 REQUIRE(timeline->checkConsistency()); 1316 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 1317 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1318 REQUIRE(timeline->getClipPosition(cid1) == 2 * length); 1319 REQUIRE(undoStack->index() == init_index + 2); 1320 CHECK_MOVE(0); 1321 1322 undoStack->undo(); 1323 CHECK_MOVE(0); 1324 undoStack->undo(); 1325 REQUIRE(timeline->checkConsistency()); 1326 REQUIRE(timeline->getTrackClipsCount(tid1) == 0); 1327 REQUIRE(timeline->getClipTrackId(cid1) == -1); 1328 REQUIRE(undoStack->index() == init_index); 1329 CHECK_REMOVE(Once); 1330 } 1331 1332 SECTION("Basic resize orphan clip undo") 1333 { 1334 REQUIRE(timeline->getClipPlaytime(cid2) == length); 1335 1336 REQUIRE(timeline->requestItemResize(cid2, length - 5, true) == length - 5); 1337 REQUIRE(undoStack->index() == init_index + 1); 1338 REQUIRE(timeline->getClipPlaytime(cid2) == length - 5); 1339 1340 REQUIRE(timeline->requestItemResize(cid2, length - 10, false) == length - 10); 1341 REQUIRE(undoStack->index() == init_index + 2); 1342 REQUIRE(timeline->getClipPlaytime(cid2) == length - 10); 1343 1344 REQUIRE(timeline->requestItemResize(cid2, length, false) == -1); 1345 REQUIRE(undoStack->index() == init_index + 2); 1346 REQUIRE(timeline->getClipPlaytime(cid2) == length - 10); 1347 1348 undoStack->undo(); 1349 REQUIRE(undoStack->index() == init_index + 1); 1350 REQUIRE(timeline->getClipPlaytime(cid2) == length - 5); 1351 1352 undoStack->redo(); 1353 REQUIRE(undoStack->index() == init_index + 2); 1354 REQUIRE(timeline->getClipPlaytime(cid2) == length - 10); 1355 1356 undoStack->undo(); 1357 REQUIRE(undoStack->index() == init_index + 1); 1358 REQUIRE(timeline->getClipPlaytime(cid2) == length - 5); 1359 1360 undoStack->undo(); 1361 REQUIRE(undoStack->index() == init_index); 1362 REQUIRE(timeline->getClipPlaytime(cid2) == length); 1363 } 1364 SECTION("Basic resize inserted clip undo") 1365 { 1366 REQUIRE(timeline->getClipPlaytime(cid2) == length); 1367 __anond6fdc6cc2702(int pos, int l) 1368 auto check = [&](int pos, int l) { 1369 REQUIRE(timeline->checkConsistency()); 1370 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 1371 REQUIRE(timeline->getClipTrackId(cid2) == tid1); 1372 REQUIRE(timeline->getClipPlaytime(cid2) == l); 1373 REQUIRE(timeline->getClipPosition(cid2) == pos); 1374 }; 1375 REQUIRE(timeline->requestClipMove(cid2, tid1, 5)); 1376 INFO("Test 1"); 1377 check(5, length); 1378 REQUIRE(undoStack->index() == init_index + 1); 1379 1380 REQUIRE(timeline->requestItemResize(cid2, length - 5, true) == length - 5); 1381 INFO("Test 2"); 1382 check(5, length - 5); 1383 REQUIRE(undoStack->index() == init_index + 2); 1384 1385 REQUIRE(timeline->requestItemResize(cid2, length - 10, false) == length - 10); 1386 INFO("Test 3"); 1387 check(10, length - 10); 1388 REQUIRE(undoStack->index() == init_index + 3); 1389 1390 REQUIRE(timeline->requestItemResize(cid2, length, false) == -1); 1391 INFO("Test 4"); 1392 check(10, length - 10); 1393 REQUIRE(undoStack->index() == init_index + 3); 1394 1395 undoStack->undo(); 1396 INFO("Test 5"); 1397 check(5, length - 5); 1398 REQUIRE(undoStack->index() == init_index + 2); 1399 1400 undoStack->redo(); 1401 INFO("Test 6"); 1402 check(10, length - 10); 1403 REQUIRE(undoStack->index() == init_index + 3); 1404 1405 undoStack->undo(); 1406 INFO("Test 7"); 1407 check(5, length - 5); 1408 REQUIRE(undoStack->index() == init_index + 2); 1409 1410 undoStack->undo(); 1411 INFO("Test 8"); 1412 check(5, length); 1413 REQUIRE(undoStack->index() == init_index + 1); 1414 } 1415 SECTION("Clip Insertion Undo") 1416 { 1417 QString binId3 = createProducer(profile_model, "red", binModel); 1418 1419 REQUIRE(timeline->requestClipMove(cid1, tid1, 5)); __anond6fdc6cc2802() 1420 auto state1 = [&]() { 1421 REQUIRE(timeline->checkConsistency()); 1422 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 1423 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1424 REQUIRE(timeline->getClipPosition(cid1) == 5); 1425 REQUIRE(undoStack->index() == init_index + 1); 1426 }; 1427 state1(); 1428 1429 int cid3; 1430 REQUIRE_FALSE(timeline->requestClipInsertion(binId3, tid1, 5, cid3)); 1431 state1(); 1432 1433 REQUIRE_FALSE(timeline->requestClipInsertion(binId3, tid1, 6, cid3)); 1434 state1(); 1435 1436 REQUIRE(timeline->requestClipInsertion(binId3, tid1, 5 + length, cid3)); __anond6fdc6cc2902() 1437 auto state2 = [&]() { 1438 REQUIRE(timeline->checkConsistency()); 1439 REQUIRE(timeline->getTrackClipsCount(tid1) == 2); 1440 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1441 REQUIRE(timeline->getClipTrackId(cid3) == tid1); 1442 REQUIRE(timeline->getClipPosition(cid1) == 5); 1443 REQUIRE(timeline->getClipPosition(cid3) == 5 + length); 1444 REQUIRE(timeline->m_allClips[cid3]->isValid()); 1445 REQUIRE(undoStack->index() == init_index + 2); 1446 }; 1447 state2(); 1448 1449 REQUIRE(timeline->requestClipMove(cid3, tid1, 10 + length)); __anond6fdc6cc2a02() 1450 auto state3 = [&]() { 1451 REQUIRE(timeline->checkConsistency()); 1452 REQUIRE(timeline->getTrackClipsCount(tid1) == 2); 1453 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1454 REQUIRE(timeline->getClipTrackId(cid3) == tid1); 1455 REQUIRE(timeline->getClipPosition(cid1) == 5); 1456 REQUIRE(timeline->getClipPosition(cid3) == 10 + length); 1457 REQUIRE(undoStack->index() == init_index + 3); 1458 }; 1459 state3(); 1460 1461 REQUIRE(timeline->requestItemResize(cid3, 1, true) == 1); __anond6fdc6cc2b02() 1462 auto state4 = [&]() { 1463 REQUIRE(timeline->checkConsistency()); 1464 REQUIRE(timeline->getTrackClipsCount(tid1) == 2); 1465 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1466 REQUIRE(timeline->getClipTrackId(cid3) == tid1); 1467 REQUIRE(timeline->getClipPosition(cid1) == 5); 1468 REQUIRE(timeline->getClipPlaytime(cid3) == 1); 1469 REQUIRE(timeline->getClipPosition(cid3) == 10 + length); 1470 REQUIRE(undoStack->index() == init_index + 4); 1471 }; 1472 state4(); 1473 1474 undoStack->undo(); 1475 state3(); 1476 1477 undoStack->undo(); 1478 state2(); 1479 1480 undoStack->undo(); 1481 state1(); 1482 1483 undoStack->redo(); 1484 state2(); 1485 1486 undoStack->redo(); 1487 state3(); 1488 1489 undoStack->redo(); 1490 state4(); 1491 1492 undoStack->undo(); 1493 state3(); 1494 1495 undoStack->undo(); 1496 state2(); 1497 1498 undoStack->undo(); 1499 state1(); 1500 } 1501 1502 SECTION("Clip Deletion undo") 1503 { 1504 REQUIRE(timeline->requestClipMove(cid1, tid1, 5)); __anond6fdc6cc2c02() 1505 auto state1 = [&]() { 1506 REQUIRE(timeline->checkConsistency()); 1507 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 1508 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1509 REQUIRE(timeline->getClipPosition(cid1) == 5); 1510 REQUIRE(undoStack->index() == init_index + 1); 1511 }; 1512 state1(); 1513 1514 int nbClips = timeline->getClipsCount(); 1515 REQUIRE(timeline->requestItemDeletion(cid1)); __anond6fdc6cc2d02() 1516 auto state2 = [&]() { 1517 REQUIRE(timeline->checkConsistency()); 1518 REQUIRE(timeline->getTrackClipsCount(tid1) == 0); 1519 REQUIRE(timeline->getClipsCount() == nbClips - 1); 1520 REQUIRE(undoStack->index() == init_index + 2); 1521 }; 1522 state2(); 1523 1524 undoStack->undo(); 1525 state1(); 1526 1527 undoStack->redo(); 1528 state2(); 1529 1530 undoStack->undo(); 1531 state1(); 1532 } 1533 1534 SECTION("Select then delete") 1535 { 1536 REQUIRE(timeline->requestClipMove(cid1, tid1, 5)); 1537 REQUIRE(timeline->requestClipMove(cid2, tid2, 1)); __anond6fdc6cc2e02() 1538 auto state1 = [&]() { 1539 REQUIRE(timeline->checkConsistency()); 1540 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 1541 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1542 REQUIRE(timeline->getClipPosition(cid1) == 5); 1543 REQUIRE(timeline->getTrackClipsCount(tid2) == 1); 1544 REQUIRE(timeline->getClipTrackId(cid2) == tid2); 1545 REQUIRE(timeline->getClipPosition(cid2) == 1); 1546 }; 1547 state1(); 1548 1549 REQUIRE(timeline->requestSetSelection({cid1, cid2})); 1550 int nbClips = timeline->getClipsCount(); 1551 REQUIRE(timeline->requestItemDeletion(cid1)); __anond6fdc6cc2f02() 1552 auto state2 = [&]() { 1553 REQUIRE(timeline->checkConsistency()); 1554 REQUIRE(timeline->getTrackClipsCount(tid1) == 0); 1555 REQUIRE(timeline->getTrackClipsCount(tid2) == 0); 1556 REQUIRE(timeline->getClipsCount() == nbClips - 2); 1557 }; 1558 state2(); 1559 1560 undoStack->undo(); 1561 state1(); 1562 1563 undoStack->redo(); 1564 state2(); 1565 1566 undoStack->undo(); 1567 state1(); 1568 } 1569 1570 SECTION("Track insertion undo") 1571 { 1572 std::map<int, int> orig_trackPositions, final_trackPositions; 1573 for (const auto &it : timeline->m_iteratorTable) { 1574 int track = it.first; 1575 int pos = timeline->getTrackPosition(track); 1576 orig_trackPositions[track] = pos; 1577 if (pos >= 1) pos++; 1578 final_trackPositions[track] = pos; 1579 } __anond6fdc6cc3002(const std::map<int, int> &pos) 1580 auto checkPositions = [&](const std::map<int, int> &pos) { 1581 for (const auto &p : pos) { 1582 REQUIRE(timeline->getTrackPosition(p.first) == p.second); 1583 } 1584 }; 1585 checkPositions(orig_trackPositions); 1586 int new_tid; 1587 REQUIRE(timeline->requestTrackInsertion(1, new_tid)); 1588 checkPositions(final_trackPositions); 1589 1590 undoStack->undo(); 1591 checkPositions(orig_trackPositions); 1592 1593 undoStack->redo(); 1594 checkPositions(final_trackPositions); 1595 1596 undoStack->undo(); 1597 checkPositions(orig_trackPositions); 1598 } 1599 1600 SECTION("Track deletion undo") 1601 { 1602 int nb_clips = timeline->getClipsCount(); 1603 int nb_tracks = timeline->getTracksCount(); 1604 REQUIRE(timeline->requestClipMove(cid1, tid1, 5)); __anond6fdc6cc3102() 1605 auto state1 = [&]() { 1606 REQUIRE(timeline->checkConsistency()); 1607 REQUIRE(timeline->getTrackClipsCount(tid1) == 1); 1608 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1609 REQUIRE(timeline->getClipPosition(cid1) == 5); 1610 REQUIRE(undoStack->index() == init_index + 1); 1611 REQUIRE(timeline->getClipsCount() == nb_clips); 1612 REQUIRE(timeline->getTracksCount() == nb_tracks); 1613 }; 1614 state1(); 1615 1616 REQUIRE(timeline->requestTrackDeletion(tid1)); 1617 REQUIRE(timeline->getClipsCount() == nb_clips - 1); 1618 REQUIRE(timeline->getTracksCount() == nb_tracks - 1); 1619 1620 undoStack->undo(); 1621 state1(); 1622 1623 undoStack->redo(); 1624 REQUIRE(timeline->getClipsCount() == nb_clips - 1); 1625 REQUIRE(timeline->getTracksCount() == nb_tracks - 1); 1626 1627 undoStack->undo(); 1628 state1(); 1629 } 1630 1631 int clipCount = timeline->m_allClips.size(); 1632 SECTION("Clip creation and resize") 1633 { 1634 int cid6; __anond6fdc6cc3202() 1635 auto state0 = [&]() { 1636 REQUIRE(timeline->m_allClips.size() == clipCount); 1637 REQUIRE(timeline->checkConsistency()); 1638 }; 1639 state0(); 1640 1641 { __anond6fdc6cc3302() 1642 std::function<bool(void)> undo = []() { return true; }; __anond6fdc6cc3402() 1643 std::function<bool(void)> redo = []() { return true; }; 1644 REQUIRE(timeline->requestClipCreation(binId, cid6, PlaylistState::VideoOnly, 1, 1., false, undo, redo)); 1645 pCore->pushUndo(undo, redo, QString()); 1646 } 1647 int l = timeline->getClipPlaytime(cid6); 1648 __anond6fdc6cc3502() 1649 auto state1 = [&]() { 1650 REQUIRE(timeline->m_allClips.size() == clipCount + 1); 1651 REQUIRE(timeline->isClip(cid6)); 1652 REQUIRE(timeline->getClipTrackId(cid6) == -1); 1653 REQUIRE(timeline->getClipPlaytime(cid6) == l); 1654 }; 1655 state1(); 1656 1657 { __anond6fdc6cc3602() 1658 std::function<bool(void)> undo = []() { return true; }; __anond6fdc6cc3702() 1659 std::function<bool(void)> redo = []() { return true; }; 1660 int size = l - 5; 1661 REQUIRE(timeline->requestItemResize(cid6, size, true, true, undo, redo, false)); 1662 pCore->pushUndo(undo, redo, QString()); 1663 } __anond6fdc6cc3802() 1664 auto state2 = [&]() { 1665 REQUIRE(timeline->m_allClips.size() == clipCount + 1); 1666 REQUIRE(timeline->isClip(cid6)); 1667 REQUIRE(timeline->getClipTrackId(cid6) == -1); 1668 REQUIRE(timeline->getClipPlaytime(cid6) == l - 5); 1669 }; 1670 state2(); 1671 1672 { __anond6fdc6cc3902() 1673 std::function<bool(void)> undo = []() { return true; }; __anond6fdc6cc3a02() 1674 std::function<bool(void)> redo = []() { return true; }; 1675 REQUIRE(timeline->requestClipMove(cid6, tid1, 7, true, true, true, true, undo, redo)); 1676 pCore->pushUndo(undo, redo, QString()); 1677 } __anond6fdc6cc3b02() 1678 auto state3 = [&]() { 1679 REQUIRE(timeline->m_allClips.size() == clipCount + 1); 1680 REQUIRE(timeline->isClip(cid6)); 1681 REQUIRE(timeline->getClipTrackId(cid6) == tid1); 1682 REQUIRE(timeline->getClipPosition(cid6) == 7); 1683 REQUIRE(timeline->getClipPlaytime(cid6) == l - 5); 1684 }; 1685 state3(); 1686 1687 { __anond6fdc6cc3c02() 1688 std::function<bool(void)> undo = []() { return true; }; __anond6fdc6cc3d02() 1689 std::function<bool(void)> redo = []() { return true; }; 1690 int size = l - 6; 1691 REQUIRE(timeline->requestItemResize(cid6, size, false, true, undo, redo, false)); 1692 pCore->pushUndo(undo, redo, QString()); 1693 } __anond6fdc6cc3e02() 1694 auto state4 = [&]() { 1695 REQUIRE(timeline->m_allClips.size() == clipCount + 1); 1696 REQUIRE(timeline->isClip(cid6)); 1697 REQUIRE(timeline->getClipTrackId(cid6) == tid1); 1698 REQUIRE(timeline->getClipPosition(cid6) == 8); 1699 REQUIRE(timeline->getClipPlaytime(cid6) == l - 6); 1700 }; 1701 state4(); 1702 1703 undoStack->undo(); 1704 state3(); 1705 undoStack->undo(); 1706 state2(); 1707 undoStack->undo(); 1708 state1(); 1709 undoStack->undo(); 1710 state0(); 1711 undoStack->redo(); 1712 state1(); 1713 undoStack->redo(); 1714 state2(); 1715 undoStack->redo(); 1716 state3(); 1717 undoStack->redo(); 1718 state4(); 1719 } 1720 binModel->clean(); 1721 pCore->m_projectManager = nullptr; 1722 } 1723 1724 TEST_CASE("Snapping", "[Snapping]") 1725 { 1726 auto binModel = pCore->projectItemModel(); 1727 binModel->clean(); 1728 std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr); 1729 std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack); 1730 1731 // Here we do some trickery to enable testing. 1732 // We mock the project class so that the undoStack function returns our undoStack 1733 1734 Mock<ProjectManager> pmMock; 1735 When(Method(pmMock, undoStack)).AlwaysReturn(undoStack); 1736 When(Method(pmMock, cacheDir)).AlwaysReturn(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))); 1737 1738 ProjectManager &mocked = pmMock.get(); 1739 pCore->m_projectManager = &mocked; 1740 1741 // We also mock timeline object to spy few functions and mock others 1742 TimelineItemModel tim(&profile_model, undoStack); 1743 Mock<TimelineItemModel> timMock(tim); __anond6fdc6cc3f02(...) 1744 auto timeline = std::shared_ptr<TimelineItemModel>(&timMock.get(), [](...) {}); 1745 TimelineItemModel::finishConstruct(timeline, guideModel); 1746 1747 RESET(timMock); 1748 1749 QString binId = createProducer(profile_model, "red", binModel, 50); 1750 QString binId2 = createProducer(profile_model, "blue", binModel); 1751 1752 int tid1 = TrackModel::construct(timeline); 1753 int cid1 = ClipModel::construct(timeline, binId, -1, PlaylistState::VideoOnly); 1754 int tid2 = TrackModel::construct(timeline); 1755 int cid2 = ClipModel::construct(timeline, binId2, -1, PlaylistState::VideoOnly); 1756 1757 int length = timeline->getClipPlaytime(cid1); 1758 int length2 = timeline->getClipPlaytime(cid2); 1759 SECTION("getBlankSizeNearClip") 1760 { 1761 REQUIRE(timeline->requestClipMove(cid1, tid1, 0)); 1762 1763 // before 1764 REQUIRE(timeline->getTrackById(tid1)->getBlankSizeNearClip(cid1, false) == 0); 1765 // after 1766 REQUIRE(timeline->getTrackById(tid1)->getBlankSizeNearClip(cid1, true) == INT_MAX); 1767 REQUIRE(timeline->requestClipMove(cid1, tid1, 10)); 1768 // before 1769 REQUIRE(timeline->getTrackById(tid1)->getBlankSizeNearClip(cid1, false) == 10); 1770 // after 1771 REQUIRE(timeline->getTrackById(tid1)->getBlankSizeNearClip(cid1, true) == INT_MAX); 1772 REQUIRE(timeline->requestClipMove(cid2, tid1, 25 + length)); 1773 // before 1774 REQUIRE(timeline->getTrackById(tid1)->getBlankSizeNearClip(cid1, false) == 10); 1775 REQUIRE(timeline->getTrackById(tid1)->getBlankSizeNearClip(cid2, false) == 15); 1776 // after 1777 REQUIRE(timeline->getTrackById(tid1)->getBlankSizeNearClip(cid1, true) == 15); 1778 REQUIRE(timeline->getTrackById(tid1)->getBlankSizeNearClip(cid2, true) == INT_MAX); 1779 1780 REQUIRE(timeline->requestClipMove(cid2, tid1, 10 + length)); 1781 // before 1782 REQUIRE(timeline->getTrackById(tid1)->getBlankSizeNearClip(cid1, false) == 10); 1783 REQUIRE(timeline->getTrackById(tid1)->getBlankSizeNearClip(cid2, false) == 0); 1784 // after 1785 REQUIRE(timeline->getTrackById(tid1)->getBlankSizeNearClip(cid1, true) == 0); 1786 REQUIRE(timeline->getTrackById(tid1)->getBlankSizeNearClip(cid2, true) == INT_MAX); 1787 } 1788 SECTION("Snap move to a single clip") 1789 { 1790 int beg = 30; 1791 // in the absence of other clips, a valid move shouldn't be modified 1792 for (int snap = -1; snap <= 5; ++snap) { 1793 REQUIRE(timeline->suggestClipMove(cid2, tid2, beg, -1, snap).at(0) == beg); 1794 REQUIRE(timeline->suggestClipMove(cid2, tid2, beg + length, -1, snap).at(0) == beg + length); 1795 REQUIRE(timeline->checkConsistency()); 1796 } 1797 1798 // We add a clip in first track to create snap points 1799 REQUIRE(timeline->requestClipMove(cid1, tid1, beg)); 1800 1801 // Now a clip in second track should snap to beginning __anond6fdc6cc4002(int pos, int perturb, int snap) 1802 auto check_snap = [&](int pos, int perturb, int snap) { 1803 if (snap >= perturb) { 1804 REQUIRE(timeline->suggestClipMove(cid2, tid2, pos + perturb, -1, snap).at(0) == pos); 1805 REQUIRE(timeline->suggestClipMove(cid2, tid2, pos - perturb, -1, snap).at(0) == pos); 1806 } else { 1807 REQUIRE(timeline->suggestClipMove(cid2, tid2, pos + perturb, -1, snap).at(0) == pos + perturb); 1808 REQUIRE(timeline->suggestClipMove(cid2, tid2, pos - perturb, -1, snap).at(0) == pos - perturb); 1809 } 1810 }; 1811 for (int snap = -1; snap <= 5; ++snap) { 1812 for (int perturb = 0; perturb <= 6; ++perturb) { 1813 // snap to beginning 1814 check_snap(beg, perturb, snap); 1815 check_snap(beg + length, perturb, snap); 1816 // snap to end 1817 check_snap(beg - length2, perturb, snap); 1818 check_snap(beg + length - length2, perturb, snap); 1819 REQUIRE(timeline->checkConsistency()); 1820 } 1821 } 1822 1823 // Same test, but now clip is moved in position 0 first 1824 REQUIRE(timeline->requestClipMove(cid2, tid2, 0)); 1825 for (int snap = -1; snap <= 5; ++snap) { 1826 for (int perturb = 0; perturb <= 6; ++perturb) { 1827 // snap to beginning 1828 check_snap(beg, perturb, snap); 1829 check_snap(beg + length, perturb, snap); 1830 // snap to end 1831 check_snap(beg - length2, perturb, snap); 1832 check_snap(beg + length - length2, perturb, snap); 1833 REQUIRE(timeline->checkConsistency()); 1834 } 1835 } 1836 } 1837 binModel->clean(); 1838 pCore->m_projectManager = nullptr; 1839 } 1840 1841 TEST_CASE("Operations under locked tracks", "[Locked]") 1842 { 1843 1844 QString aCompo; 1845 // Look for a compo 1846 QVector<QPair<QString, QString>> transitions = TransitionsRepository::get()->getNames(); 1847 for (const auto &trans : qAsConst(transitions)) { 1848 if (TransitionsRepository::get()->isComposition(trans.first)) { 1849 aCompo = trans.first; 1850 break; 1851 } 1852 } 1853 REQUIRE(!aCompo.isEmpty()); 1854 1855 auto binModel = pCore->projectItemModel(); 1856 binModel->clean(); 1857 std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr); 1858 std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack); 1859 1860 // Here we do some trickery to enable testing. 1861 // We mock the project class so that the undoStack function returns our undoStack 1862 1863 Mock<ProjectManager> pmMock; 1864 When(Method(pmMock, undoStack)).AlwaysReturn(undoStack); 1865 When(Method(pmMock, cacheDir)).AlwaysReturn(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))); 1866 1867 ProjectManager &mocked = pmMock.get(); 1868 pCore->m_projectManager = &mocked; 1869 1870 // We also mock timeline object to spy few functions and mock others 1871 TimelineItemModel tim(&profile_model, undoStack); 1872 Mock<TimelineItemModel> timMock(tim); __anond6fdc6cc4102(...) 1873 auto timeline = std::shared_ptr<TimelineItemModel>(&timMock.get(), [](...) {}); 1874 TimelineItemModel::finishConstruct(timeline, guideModel); 1875 1876 Fake(Method(timMock, adjustAssetRange)); 1877 1878 // This is faked to allow to count calls 1879 Fake(Method(timMock, _beginInsertRows)); 1880 Fake(Method(timMock, _beginRemoveRows)); 1881 Fake(Method(timMock, _endInsertRows)); 1882 Fake(Method(timMock, _endRemoveRows)); 1883 1884 QString binId = createProducer(profile_model, "red", binModel); 1885 QString binId3 = createProducerWithSound(profile_model, binModel); 1886 1887 int tid1, tid2, tid3; 1888 REQUIRE(timeline->requestTrackInsertion(-1, tid1)); 1889 REQUIRE(timeline->requestTrackInsertion(-1, tid2)); 1890 REQUIRE(timeline->requestTrackInsertion(-1, tid3)); 1891 1892 RESET(timMock); 1893 1894 SECTION("Locked track can't receive insertion") 1895 { 1896 timeline->setTrackLockedState(tid1, true); 1897 REQUIRE(timeline->getTrackById(tid1)->isLocked()); 1898 REQUIRE(timeline->getClipsCount() == 0); 1899 REQUIRE(timeline->checkConsistency()); 1900 int cid1 = -1; 1901 REQUIRE_FALSE(timeline->requestClipInsertion(binId, tid1, 2, cid1)); 1902 REQUIRE(timeline->getClipsCount() == 0); 1903 REQUIRE(timeline->checkConsistency()); 1904 REQUIRE(cid1 == -1); 1905 1906 // now unlock and check that insertion becomes possible again 1907 timeline->setTrackLockedState(tid1, false); 1908 REQUIRE_FALSE(timeline->getTrackById(tid1)->isLocked()); 1909 REQUIRE(timeline->getClipsCount() == 0); 1910 REQUIRE(timeline->checkConsistency()); 1911 REQUIRE(timeline->requestClipInsertion(binId, tid1, 2, cid1)); 1912 REQUIRE(timeline->getClipsCount() == 1); 1913 REQUIRE(timeline->checkConsistency()); 1914 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1915 REQUIRE(timeline->getClipPosition(cid1) == 2); 1916 } 1917 SECTION("Can't move clip on locked track") 1918 { 1919 int cid1 = -1; 1920 REQUIRE(timeline->requestClipInsertion(binId, tid1, 2, cid1)); 1921 REQUIRE(timeline->getClipsCount() == 1); 1922 REQUIRE(timeline->checkConsistency()); 1923 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1924 REQUIRE(timeline->getClipPosition(cid1) == 2); 1925 // not yet locked, move should work 1926 REQUIRE(timeline->requestClipMove(cid1, tid1, 4)); 1927 REQUIRE(timeline->getClipPosition(cid1) == 4); 1928 REQUIRE(timeline->checkConsistency()); 1929 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1930 1931 timeline->setTrackLockedState(tid1, true); 1932 REQUIRE(timeline->getTrackById(tid1)->isLocked()); 1933 REQUIRE(timeline->checkConsistency()); 1934 REQUIRE(timeline->getClipsCount() == 1); 1935 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1936 REQUIRE(timeline->getClipPosition(cid1) == 4); 1937 1938 REQUIRE_FALSE(timeline->requestClipMove(cid1, tid1, 6)); 1939 1940 REQUIRE(timeline->getTrackById(tid1)->isLocked()); 1941 REQUIRE(timeline->checkConsistency()); 1942 REQUIRE(timeline->getClipsCount() == 1); 1943 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1944 REQUIRE(timeline->getClipPosition(cid1) == 4); 1945 1946 // unlock, move should work again 1947 timeline->setTrackLockedState(tid1, false); 1948 REQUIRE_FALSE(timeline->getTrackById(tid1)->isLocked()); 1949 REQUIRE(timeline->checkConsistency()); 1950 REQUIRE(timeline->requestClipMove(cid1, tid1, 6)); 1951 REQUIRE(timeline->getClipsCount() == 1); 1952 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 1953 REQUIRE(timeline->getClipPosition(cid1) == 6); 1954 REQUIRE(timeline->checkConsistency()); 1955 } 1956 SECTION("Can't move composition on locked track") 1957 { 1958 int compo = CompositionModel::construct(timeline, aCompo, QString()); 1959 timeline->setTrackLockedState(tid1, true); 1960 REQUIRE(timeline->getTrackById(tid1)->isLocked()); 1961 REQUIRE(timeline->checkConsistency()); 1962 1963 REQUIRE(timeline->getCompositionTrackId(compo) == -1); 1964 REQUIRE(timeline->getTrackCompositionsCount(tid1) == 0); 1965 int pos = 10; 1966 REQUIRE_FALSE(timeline->requestCompositionMove(compo, tid1, pos)); 1967 REQUIRE(timeline->checkConsistency()); 1968 REQUIRE(timeline->getCompositionTrackId(compo) == -1); 1969 REQUIRE(timeline->getTrackCompositionsCount(tid1) == 0); 1970 1971 // unlock to be able to insert 1972 timeline->setTrackLockedState(tid1, false); 1973 REQUIRE_FALSE(timeline->getTrackById(tid1)->isLocked()); 1974 REQUIRE(timeline->checkConsistency()); 1975 REQUIRE(timeline->requestCompositionMove(compo, tid1, pos)); 1976 REQUIRE(timeline->checkConsistency()); 1977 REQUIRE(timeline->getCompositionTrackId(compo) == tid1); 1978 REQUIRE(timeline->getTrackCompositionsCount(tid1) == 1); 1979 REQUIRE(timeline->getCompositionPosition(compo) == pos); 1980 1981 // relock 1982 timeline->setTrackLockedState(tid1, true); 1983 REQUIRE(timeline->getTrackById(tid1)->isLocked()); 1984 REQUIRE(timeline->checkConsistency()); 1985 REQUIRE_FALSE(timeline->requestCompositionMove(compo, tid1, pos + 10)); 1986 REQUIRE(timeline->checkConsistency()); 1987 REQUIRE(timeline->getCompositionTrackId(compo) == tid1); 1988 REQUIRE(timeline->getTrackCompositionsCount(tid1) == 1); 1989 REQUIRE(timeline->getCompositionPosition(compo) == pos); 1990 } 1991 SECTION("Can't resize clip on locked track") 1992 { 1993 int cid1 = -1; 1994 REQUIRE(timeline->requestClipInsertion(binId, tid1, 2, cid1)); 1995 REQUIRE(timeline->getClipsCount() == 1); 1996 __anond6fdc6cc4202(int l) 1997 auto check = [&](int l) { 1998 REQUIRE(timeline->checkConsistency()); 1999 REQUIRE(timeline->getClipTrackId(cid1) == tid1); 2000 REQUIRE(timeline->getClipPosition(cid1) == 2); 2001 REQUIRE(timeline->getClipPlaytime(cid1) == l); 2002 }; 2003 check(20); 2004 2005 // not yet locked, resize should work 2006 REQUIRE(timeline->requestItemResize(cid1, 18, true) == 18); 2007 check(18); 2008 2009 // lock 2010 timeline->setTrackLockedState(tid1, true); 2011 REQUIRE(timeline->getTrackById(tid1)->isLocked()); 2012 check(18); 2013 REQUIRE(timeline->requestItemResize(cid1, 17, true) == -1); 2014 check(18); 2015 REQUIRE(timeline->requestItemResize(cid1, 17, false) == -1); 2016 check(18); 2017 REQUIRE(timeline->requestItemResize(cid1, 19, true) == -1); 2018 check(18); 2019 REQUIRE(timeline->requestItemResize(cid1, 19, false) == -1); 2020 check(18); 2021 2022 // unlock, resize should work again 2023 timeline->setTrackLockedState(tid1, false); 2024 REQUIRE_FALSE(timeline->getTrackById(tid1)->isLocked()); 2025 check(18); 2026 REQUIRE(timeline->requestItemResize(cid1, 17, true) == 17); 2027 check(17); 2028 } 2029 SECTION("Can't resize composition on locked track") 2030 { 2031 int compo = CompositionModel::construct(timeline, aCompo, QString()); 2032 REQUIRE(timeline->requestCompositionMove(compo, tid1, 2)); 2033 REQUIRE(timeline->requestItemResize(compo, 20, true) == 20); 2034 __anond6fdc6cc4302(int l) 2035 auto check = [&](int l) { 2036 REQUIRE(timeline->checkConsistency()); 2037 REQUIRE(timeline->getCompositionsCount() == 1); 2038 REQUIRE(timeline->getCompositionTrackId(compo) == tid1); 2039 REQUIRE(timeline->getCompositionPosition(compo) == 2); 2040 REQUIRE(timeline->getCompositionPlaytime(compo) == l); 2041 }; 2042 check(20); 2043 2044 // not yet locked, resize should work 2045 REQUIRE(timeline->requestItemResize(compo, 18, true) == 18); 2046 check(18); 2047 2048 // lock 2049 timeline->setTrackLockedState(tid1, true); 2050 REQUIRE(timeline->getTrackById(tid1)->isLocked()); 2051 check(18); 2052 REQUIRE(timeline->requestItemResize(compo, 17, true) == -1); 2053 check(18); 2054 REQUIRE(timeline->requestItemResize(compo, 17, false) == -1); 2055 check(18); 2056 REQUIRE(timeline->requestItemResize(compo, 19, true) == -1); 2057 check(18); 2058 REQUIRE(timeline->requestItemResize(compo, 19, false) == -1); 2059 check(18); 2060 2061 // unlock, resize should work again 2062 timeline->setTrackLockedState(tid1, false); 2063 REQUIRE_FALSE(timeline->getTrackById(tid1)->isLocked()); 2064 check(18); 2065 REQUIRE(timeline->requestItemResize(compo, 17, true) == 17); 2066 check(17); 2067 } 2068 2069 binModel->clean(); 2070 pCore->m_projectManager = nullptr; 2071 } 2072 2073