File indexing completed on 2024-12-01 04:29:41

0001 /*
0002     SPDX-FileCopyrightText: 2018-2022 Jean-Baptiste Mardelle <jb@kdenlive.org>
0003     SPDX-FileCopyrightText: 2017-2019 Nicolas Carion <french.ebook.lover@gmail.com>
0004     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #include "test_utils.hpp"
0008 // test specific includes
0009 #include "doc/docundostack.hpp"
0010 #include "doc/kdenlivedoc.h"
0011 #include <memory>
0012 
0013 using namespace fakeit;
0014 
0015 bool test_model_equality(const std::shared_ptr<KeyframeModel> &m1, const std::shared_ptr<KeyframeModel> &m2)
0016 {
0017     // we cheat a bit by simply comparing the underlying map
0018     qDebug() << "Equality test" << m1->m_keyframeList.size() << m2->m_keyframeList.size();
0019     QList<QVariant> model1;
0020     QList<QVariant> model2;
0021     for (const auto &m : m1->m_keyframeList) {
0022         model1 << m.first.frames(25) << (int)m.second.first << m.second.second;
0023     }
0024     for (const auto &m : m2->m_keyframeList) {
0025         model2 << m.first.frames(25) << (int)m.second.first << m.second.second;
0026     }
0027     return model1 == model2;
0028 }
0029 
0030 bool check_anim_identity(const std::shared_ptr<KeyframeModel> &m)
0031 {
0032     auto m2 = std::make_shared<KeyframeModel>(m->m_model, m->m_index, m->m_undoStack);
0033     m2->parseAnimProperty(m->getAnimProperty());
0034     return test_model_equality(m, m2);
0035 }
0036 
0037 TEST_CASE("Keyframe model", "[KeyframeModel]")
0038 {
0039     // Create timeline
0040     auto binModel = pCore->projectItemModel();
0041     std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
0042 
0043     // Here we do some trickery to enable testing.
0044     // We mock the project class so that the undoStack function returns our undoStack
0045     KdenliveDoc document(undoStack);
0046 
0047     pCore->projectManager()->m_project = &document;
0048     QDateTime documentDate = QDateTime::currentDateTime();
0049     pCore->projectManager()->updateTimeline(false, QString(), QString(), documentDate, 0);
0050     auto timeline = document.getTimeline(document.uuid());
0051     pCore->projectManager()->m_activeTimelineModel = timeline;
0052     pCore->projectManager()->testSetActiveDocument(&document, timeline);
0053 
0054     const QString binId = createProducer(pCore->getProjectProfile(), "red", binModel, 100, false);
0055     std::shared_ptr<ProjectClip> clip = binModel->getClipByBinID(binId);
0056     auto effectstack = clip->m_effectStack;
0057 
0058     effectstack->appendEffect(QStringLiteral("audiobalance"));
0059     REQUIRE(effectstack->checkConsistency());
0060     REQUIRE(effectstack->rowCount() == 1);
0061     auto effect = std::dynamic_pointer_cast<EffectItemModel>(effectstack->getEffectStackRow(0));
0062     effect->prepareKeyframes();
0063     qDebug() << effect->getAssetId() << effect->getAllParameters();
0064 
0065     REQUIRE(effect->rowCount() == 1);
0066     QModelIndex index = effect->index(0, 0);
0067 
0068     auto model = std::make_shared<KeyframeModel>(effect, index, undoStack);
0069 
0070     SECTION("Add/remove + undo")
0071     {
0072         auto state0 = [&]() {
0073             REQUIRE(model->rowCount() == 1);
0074             REQUIRE(check_anim_identity(model));
0075         };
0076         state0();
0077 
0078         REQUIRE(model->addKeyframe(GenTime(1.1), KeyframeType::Linear, 42));
0079         auto state1 = [&]() {
0080             REQUIRE(model->rowCount() == 2);
0081             REQUIRE(check_anim_identity(model));
0082             REQUIRE(model->hasKeyframe(GenTime(1.1)));
0083             bool ok;
0084             auto k = model->getKeyframe(GenTime(1.1), &ok);
0085             REQUIRE(ok);
0086             auto k0 = model->getKeyframe(GenTime(0), &ok);
0087             REQUIRE(ok);
0088             auto k1 = model->getClosestKeyframe(GenTime(0.655555), &ok);
0089             REQUIRE(ok);
0090             REQUIRE(k1 == k);
0091             auto k2 = model->getNextKeyframe(GenTime(0.5), &ok);
0092             REQUIRE(ok);
0093             REQUIRE(k2 == k);
0094             auto k3 = model->getPrevKeyframe(GenTime(0.5), &ok);
0095             REQUIRE(ok);
0096             REQUIRE(k3 == k0);
0097             auto k4 = model->getPrevKeyframe(GenTime(10), &ok);
0098             REQUIRE(ok);
0099             REQUIRE(k4 == k);
0100             model->getNextKeyframe(GenTime(10), &ok);
0101             REQUIRE_FALSE(ok);
0102         };
0103         state1();
0104 
0105         undoStack->undo();
0106         state0();
0107         undoStack->redo();
0108         state1();
0109 
0110         REQUIRE(model->addKeyframe(GenTime(12.6), KeyframeType::Discrete, 33));
0111         auto state2 = [&]() {
0112             REQUIRE(model->rowCount() == 3);
0113             REQUIRE(check_anim_identity(model));
0114             REQUIRE(model->hasKeyframe(GenTime(1.1)));
0115             REQUIRE(model->hasKeyframe(GenTime(12.6)));
0116             bool ok;
0117             auto k = model->getKeyframe(GenTime(1.1), &ok);
0118             REQUIRE(ok);
0119             auto k0 = model->getKeyframe(GenTime(0), &ok);
0120             REQUIRE(ok);
0121             auto kk = model->getKeyframe(GenTime(12.6), &ok);
0122             REQUIRE(ok);
0123             auto k1 = model->getClosestKeyframe(GenTime(0.655555), &ok);
0124             REQUIRE(ok);
0125             REQUIRE(k1 == k);
0126             auto k2 = model->getNextKeyframe(GenTime(0.5), &ok);
0127             REQUIRE(ok);
0128             REQUIRE(k2 == k);
0129             auto k3 = model->getPrevKeyframe(GenTime(0.5), &ok);
0130             REQUIRE(ok);
0131             REQUIRE(k3 == k0);
0132             auto k4 = model->getPrevKeyframe(GenTime(10), &ok);
0133             REQUIRE(ok);
0134             REQUIRE(k4 == k);
0135             auto k5 = model->getNextKeyframe(GenTime(10), &ok);
0136             REQUIRE(ok);
0137             REQUIRE(k5 == kk);
0138         };
0139         state2();
0140 
0141         undoStack->undo();
0142         state1();
0143         undoStack->undo();
0144         state0();
0145         undoStack->redo();
0146         state1();
0147         undoStack->redo();
0148         state2();
0149 
0150         REQUIRE(model->removeKeyframe(GenTime(1.1)));
0151         auto state3 = [&]() {
0152             REQUIRE(model->rowCount() == 2);
0153             REQUIRE(check_anim_identity(model));
0154             REQUIRE(model->hasKeyframe(GenTime(12.6)));
0155             bool ok;
0156             model->getKeyframe(GenTime(1.1), &ok);
0157             REQUIRE_FALSE(ok);
0158             auto k0 = model->getKeyframe(GenTime(0), &ok);
0159             REQUIRE(ok);
0160             auto kk = model->getKeyframe(GenTime(12.6), &ok);
0161             REQUIRE(ok);
0162             auto k1 = model->getClosestKeyframe(GenTime(0.655555), &ok);
0163             REQUIRE(ok);
0164             REQUIRE(k1 == k0);
0165             auto k2 = model->getNextKeyframe(GenTime(0.5), &ok);
0166             REQUIRE(ok);
0167             REQUIRE(k2 == kk);
0168             auto k3 = model->getPrevKeyframe(GenTime(0.5), &ok);
0169             REQUIRE(ok);
0170             REQUIRE(k3 == k0);
0171             auto k4 = model->getPrevKeyframe(GenTime(10), &ok);
0172             REQUIRE(ok);
0173             REQUIRE(k4 == k0);
0174             auto k5 = model->getNextKeyframe(GenTime(10), &ok);
0175             REQUIRE(ok);
0176             REQUIRE(k5 == kk);
0177         };
0178         state3();
0179 
0180         undoStack->undo();
0181         state2();
0182         undoStack->undo();
0183         state1();
0184         undoStack->undo();
0185         state0();
0186         undoStack->redo();
0187         state1();
0188         undoStack->redo();
0189         state2();
0190         undoStack->redo();
0191         state3();
0192 
0193         REQUIRE(model->removeAllKeyframes());
0194         state0();
0195         REQUIRE(model->removeAllKeyframes());
0196         state0();
0197         undoStack->undo();
0198         state0();
0199         undoStack->undo();
0200         state3();
0201         undoStack->redo();
0202         state0();
0203     }
0204 
0205     SECTION("Move keyframes + undo")
0206     {
0207         auto state0 = [&]() {
0208             REQUIRE(model->rowCount() == 1);
0209             REQUIRE(check_anim_identity(model));
0210         };
0211         state0();
0212 
0213         REQUIRE(model->addKeyframe(GenTime(1.1), KeyframeType::Linear, 42));
0214         auto state1 = [&](double pos) {
0215             REQUIRE(model->rowCount() == 2);
0216             REQUIRE(check_anim_identity(model));
0217             REQUIRE(model->hasKeyframe(GenTime(pos)));
0218             bool ok;
0219             auto k = model->getKeyframe(GenTime(pos), &ok);
0220             REQUIRE(ok);
0221             auto k0 = model->getKeyframe(GenTime(0), &ok);
0222             REQUIRE(ok);
0223             auto k1 = model->getClosestKeyframe(GenTime(pos + 10), &ok);
0224             REQUIRE(ok);
0225             REQUIRE(k1 == k);
0226             auto k2 = model->getNextKeyframe(GenTime(pos - 0.3), &ok);
0227             REQUIRE(ok);
0228             REQUIRE(k2 == k);
0229             auto k3 = model->getPrevKeyframe(GenTime(pos - 0.3), &ok);
0230             REQUIRE(ok);
0231             REQUIRE(k3 == k0);
0232             auto k4 = model->getPrevKeyframe(GenTime(pos + 0.3), &ok);
0233             REQUIRE(ok);
0234             REQUIRE(k4 == k);
0235             model->getNextKeyframe(GenTime(pos + 0.3), &ok);
0236             REQUIRE_FALSE(ok);
0237         };
0238         state1(1.1);
0239 
0240         REQUIRE(model->moveKeyframe(GenTime(1.1), GenTime(2.6), -1, true));
0241         state1(2.6);
0242 
0243         undoStack->undo();
0244         state1(1.1);
0245         undoStack->redo();
0246         state1(2.6);
0247 
0248         REQUIRE(model->moveKeyframe(GenTime(2.6), GenTime(6.1), -1, true));
0249         state1(6.1);
0250 
0251         undoStack->undo();
0252         state1(2.6);
0253         undoStack->undo();
0254         state1(1.1);
0255         undoStack->redo();
0256         state1(2.6);
0257         undoStack->redo();
0258         state1(6.1);
0259 
0260         REQUIRE(model->addKeyframe(GenTime(12.6), KeyframeType::Discrete, 33));
0261         // Moving a keyframe past another one another will move it 1 frame before or after.
0262         REQUIRE(model->moveKeyframe(GenTime(6.1), GenTime(14), -1, true));
0263         bool ok;
0264         // There should be no keyframe after 12.6
0265         model->getNextKeyframe(GenTime(12.6), &ok);
0266         REQUIRE_FALSE(ok);
0267         undoStack->undo();
0268         undoStack->undo();
0269         state1(6.1);
0270     }
0271     clip.reset();
0272     timeline.reset();
0273     pCore->projectManager()->closeCurrentDocument(false, false);
0274 }