File indexing completed on 2024-12-08 07:28:46
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 }