File indexing completed on 2024-04-14 04:47:52

0001 /*
0002     SPDX-FileCopyrightText: 2023 Jean-Baptiste Mardelle <jb@kdenlive.org>
0003     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 #include "test_utils.hpp"
0006 // test specific headers
0007 #include "bin/binplaylist.hpp"
0008 #include "doc/kdenlivedoc.h"
0009 #include "timeline2/model/builders/meltBuilder.hpp"
0010 #include "xml/xml.hpp"
0011 
0012 #include <QTemporaryFile>
0013 #include <QUndoGroup>
0014 
0015 using namespace fakeit;
0016 
0017 TEST_CASE("Test saving sequences elements", "[TSG]")
0018 {
0019     auto binModel = pCore->projectItemModel();
0020     binModel->clean();
0021     std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
0022 
0023     SECTION("Group save")
0024     {
0025         // Create document
0026         KdenliveDoc document(undoStack);
0027         pCore->projectManager()->m_project = &document;
0028         QDateTime documentDate = QDateTime::currentDateTime();
0029         pCore->projectManager()->updateTimeline(false, QString(), QString(), documentDate, 0);
0030         auto timeline = document.getTimeline(document.uuid());
0031         pCore->projectManager()->testSetActiveDocument(&document, timeline);
0032         KdenliveDoc::next_id = 0;
0033         QDir dir = QDir::temp();
0034 
0035         QString binId = createProducerWithSound(pCore->getProjectProfile(), binModel);
0036         QString binId2 = createProducer(pCore->getProjectProfile(), "red", binModel, 20, false);
0037 
0038         int tid1 = timeline->getTrackIndexFromPosition(2);
0039 
0040         // Setup timeline audio drop info
0041         QMap<int, QString> audioInfo;
0042         audioInfo.insert(1, QStringLiteral("stream1"));
0043         timeline->m_binAudioTargets = audioInfo;
0044         timeline->m_videoTarget = tid1;
0045         // Insert 2 clips (length=20, pos = 80 / 100)
0046         int cid1 = -1;
0047         REQUIRE(timeline->requestClipInsertion(binId2, tid1, 80, cid1, true, true, false));
0048         int l = timeline->getClipPlaytime(cid1);
0049         int cid2 = -1;
0050         REQUIRE(timeline->requestClipInsertion(binId, tid1, 80 + l, cid2, true, true, false));
0051         // Resize first clip (length=100)
0052         REQUIRE(timeline->requestItemResize(cid1, 100, false) == 100);
0053 
0054         auto state = [&]() {
0055             REQUIRE(timeline->checkConsistency());
0056             REQUIRE(timeline->getTrackClipsCount(tid1) == 2);
0057             REQUIRE(timeline->getClipTrackId(cid1) == tid1);
0058             REQUIRE(timeline->getClipTrackId(cid2) == tid1);
0059             REQUIRE(timeline->getClipPosition(cid1) == 0);
0060             REQUIRE(timeline->getClipPosition(cid2) == 100);
0061             REQUIRE(timeline->getClipPlaytime(cid1) == 100);
0062             REQUIRE(timeline->getClipPlaytime(cid2) == 10);
0063         };
0064         state();
0065         REQUIRE(timeline->checkConsistency());
0066         pCore->projectManager()->testSaveFileAs(dir.absoluteFilePath(QStringLiteral("test.kdenlive")));
0067         // Undo resize
0068         undoStack->undo();
0069         // Undo first insert
0070         undoStack->undo();
0071         // Undo second insert
0072         undoStack->undo();
0073         pCore->projectManager()->closeCurrentDocument(false, false);
0074         // Reopen and check for groups
0075         QString saveFile = dir.absoluteFilePath(QStringLiteral("test.kdenlive"));
0076         QUrl openURL = QUrl::fromLocalFile(saveFile);
0077 
0078         QUndoGroup *undoGroup = new QUndoGroup(&document);
0079         undoGroup->addStack(undoStack.get());
0080         DocOpenResult openResults = KdenliveDoc::Open(openURL, QDir::temp().path(), undoGroup, false, nullptr);
0081         REQUIRE(openResults.isSuccessful() == true);
0082 
0083         std::unique_ptr<KdenliveDoc> openedDoc = openResults.getDocument();
0084         pCore->projectManager()->m_project = openedDoc.get();
0085         const QUuid uuid = openedDoc->uuid();
0086         documentDate = QFileInfo(openURL.toLocalFile()).lastModified();
0087         pCore->projectManager()->updateTimeline(false, QString(), QString(), documentDate, 0);
0088         QMap<QUuid, QString> allSequences = binModel->getAllSequenceClips();
0089         const QString firstSeqId = allSequences.value(uuid);
0090         pCore->projectManager()->openTimeline(firstSeqId, uuid);
0091         timeline = pCore->projectManager()->m_project->getTimeline(uuid);
0092         pCore->projectManager()->testSetActiveDocument(openedDoc.get(), timeline);
0093         REQUIRE(timeline->getTracksCount() == 4);
0094         REQUIRE(timeline->m_allGroups.size() == 1);
0095         timeline.reset();
0096         pCore->projectManager()->closeCurrentDocument(false, false);
0097     }
0098     SECTION("Save / Load multiple sequences")
0099     {
0100         // Create document
0101         binModel->clean();
0102         KdenliveDoc document(undoStack);
0103         pCore->projectManager()->m_project = &document;
0104         QDateTime documentDate = QDateTime::currentDateTime();
0105         pCore->projectManager()->updateTimeline(false, QString(), QString(), documentDate, 0);
0106         auto timeline = document.getTimeline(document.uuid());
0107         pCore->projectManager()->testSetActiveDocument(&document, timeline);
0108         KdenliveDoc::next_id = 0;
0109         QDir dir = QDir::temp();
0110 
0111         QString binId = createProducerWithSound(pCore->getProjectProfile(), binModel);
0112         QString binId2 = createProducer(pCore->getProjectProfile(), "red", binModel, 20, false);
0113 
0114         int tid1 = timeline->getTrackIndexFromPosition(2);
0115 
0116         // Setup timeline audio drop info
0117         QMap<int, QString> audioInfo;
0118         audioInfo.insert(1, QStringLiteral("stream1"));
0119         timeline->m_binAudioTargets = audioInfo;
0120         timeline->m_videoTarget = tid1;
0121         // Insert 2 clips (length=20, pos = 80 / 100)
0122         int cid1 = -1;
0123         REQUIRE(timeline->requestClipInsertion(binId2, tid1, 80, cid1, true, true, false));
0124         int l = timeline->getClipPlaytime(cid1);
0125         int cid2 = -1;
0126         REQUIRE(timeline->requestClipInsertion(binId, tid1, 80 + l, cid2, true, true, false));
0127         // Resize first clip (length=100)
0128         REQUIRE(timeline->requestItemResize(cid1, 100, false) == 100);
0129 
0130         auto state = [&]() {
0131             REQUIRE(timeline->checkConsistency());
0132             REQUIRE(timeline->getTrackClipsCount(tid1) == 2);
0133             REQUIRE(timeline->getClipTrackId(cid1) == tid1);
0134             REQUIRE(timeline->getClipTrackId(cid2) == tid1);
0135             REQUIRE(timeline->getClipPosition(cid1) == 0);
0136             REQUIRE(timeline->getClipPosition(cid2) == 100);
0137             REQUIRE(timeline->getClipPlaytime(cid1) == 100);
0138             REQUIRE(timeline->getClipPlaytime(cid2) == 10);
0139         };
0140         state();
0141         REQUIRE(timeline->checkConsistency());
0142         // Add secondary timeline
0143         const QString seq2 = ClipCreator::createPlaylistClip(QStringLiteral("Sequence2"), {2, 2}, QString("-1"), binModel);
0144         QMap<QUuid, QString> uids = pCore->projectItemModel()->getAllSequenceClips();
0145         QUuid secondaryUuid;
0146         QMapIterator<QUuid, QString> i(uids);
0147         while (i.hasNext()) {
0148             i.next();
0149             if (i.value() == seq2) {
0150                 secondaryUuid = i.key();
0151                 break;
0152             }
0153         }
0154         auto timeline2 = pCore->currentDoc()->getTimeline(secondaryUuid);
0155         pCore->projectManager()->m_activeTimelineModel = timeline2;
0156         tid1 = timeline2->getTrackIndexFromPosition(2);
0157         // Setup timeline audio drop info
0158         QMap<int, QString> audioInfo2;
0159         audioInfo2.insert(1, QStringLiteral("stream1"));
0160         timeline2->m_binAudioTargets = audioInfo;
0161         timeline2->m_videoTarget = tid1;
0162 
0163         int cid3 = -1;
0164         REQUIRE(timeline2->requestClipInsertion(binId, tid1, 80 + l, cid3, true, true, false));
0165         int cid4 = -1;
0166         REQUIRE(timeline2->requestClipInsertion(binId, tid1, 160 + l, cid4, true, true, false));
0167 
0168         pCore->projectManager()->m_activeTimelineModel = timeline;
0169 
0170         pCore->projectManager()->testSaveFileAs(dir.absoluteFilePath(QStringLiteral("test.kdenlive")));
0171         timeline.reset();
0172         timeline2.reset();
0173         pCore->projectManager()->closeCurrentDocument(false, false);
0174 
0175         // Reopen and check for groups
0176         QString saveFile = dir.absoluteFilePath(QStringLiteral("test.kdenlive"));
0177         QUrl openURL = QUrl::fromLocalFile(saveFile);
0178 
0179         QUndoGroup *undoGroup = new QUndoGroup(&document);
0180         undoGroup->addStack(undoStack.get());
0181         DocOpenResult openResults = KdenliveDoc::Open(openURL, QDir::temp().path(), undoGroup, false, nullptr);
0182         REQUIRE(openResults.isSuccessful() == true);
0183 
0184         std::unique_ptr<KdenliveDoc> openedDoc = openResults.getDocument();
0185         pCore->projectManager()->m_project = openedDoc.get();
0186         QUuid uuid = openedDoc->uuid();
0187         documentDate = QFileInfo(openURL.toLocalFile()).lastModified();
0188         pCore->projectManager()->updateTimeline(false, QString(), QString(), documentDate, 0);
0189         QMap<QUuid, QString> allSequences = binModel->getAllSequenceClips();
0190         QString firstSeqId = allSequences.value(uuid);
0191         QString secondSeqId = allSequences.value(secondaryUuid);
0192         pCore->projectManager()->openTimeline(firstSeqId, uuid);
0193         timeline = pCore->currentDoc()->getTimeline(uuid);
0194         pCore->projectManager()->testSetActiveDocument(openedDoc.get(), timeline);
0195         REQUIRE(timeline->getTracksCount() == 4);
0196         REQUIRE(timeline->m_allGroups.size() == 1);
0197         // pCore->projectManager()->openTimeline(secondSeqId, secondaryUuid);
0198         timeline2 = pCore->currentDoc()->getTimeline(secondaryUuid);
0199         Q_ASSERT(timeline2 != nullptr);
0200         REQUIRE(timeline2->getTracksCount() == 4);
0201         REQUIRE(timeline2->m_allGroups.size() == 2);
0202         std::shared_ptr<ProjectClip> sequenceClip = binModel->getClipByBinID(secondSeqId);
0203         REQUIRE(sequenceClip->clipName() == QLatin1String("Sequence2"));
0204         pCore->projectManager()->m_activeTimelineModel = timeline;
0205         // Save again without any changes
0206         pCore->projectManager()->testSaveFileAs(dir.absoluteFilePath(QStringLiteral("test.kdenlive")));
0207         sequenceClip.reset();
0208         timeline2.reset();
0209         timeline.reset();
0210         pCore->projectManager()->closeCurrentDocument(false, false);
0211 
0212         // Reopen test project and check closed sequence properties
0213         DocOpenResult openResults2 = KdenliveDoc::Open(openURL, QDir::temp().path(), undoGroup, false, nullptr);
0214         REQUIRE(openResults2.isSuccessful() == true);
0215 
0216         std::unique_ptr<KdenliveDoc> openedDoc2 = openResults2.getDocument();
0217         pCore->projectManager()->m_project = openedDoc2.get();
0218         uuid = openedDoc2->uuid();
0219         documentDate = QFileInfo(openURL.toLocalFile()).lastModified();
0220         pCore->projectManager()->updateTimeline(false, QString(), QString(), documentDate, 0);
0221         allSequences = binModel->getAllSequenceClips();
0222         firstSeqId = allSequences.value(uuid);
0223         secondSeqId = allSequences.value(secondaryUuid);
0224         pCore->projectManager()->openTimeline(firstSeqId, uuid);
0225         timeline = pCore->currentDoc()->getTimeline(uuid);
0226         pCore->projectManager()->testSetActiveDocument(openedDoc2.get(), timeline);
0227         REQUIRE(timeline->getTracksCount() == 4);
0228         REQUIRE(timeline->m_allGroups.size() == 1);
0229         timeline2 = pCore->currentDoc()->getTimeline(secondaryUuid);
0230         qDebug() << "::: LOOKIG FOR UUID: " << secondaryUuid << ", ALL SEQS: " << allSequences.keys();
0231         Q_ASSERT(timeline2 != nullptr);
0232         REQUIRE(timeline2->getTracksCount() == 4);
0233         REQUIRE(timeline2->m_allGroups.size() == 2);
0234         sequenceClip = binModel->getClipByBinID(secondSeqId);
0235         REQUIRE(sequenceClip->clipName() == QLatin1String("Sequence2"));
0236         sequenceClip.reset();
0237         timeline2.reset();
0238         timeline.reset();
0239         pCore->projectManager()->closeCurrentDocument(false, false);
0240     }
0241 }