1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
/*
SPDX-FileCopyrightText: 2017-2019 Nicolas Carion <french.ebook.lover@gmail.com>
SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "catch.hpp"
#include "test_utils.hpp"
// test specific headers
#include "assets/model/assetcommand.hpp"
#include "doc/docundostack.hpp"
#include "doc/kdenlivedoc.h"
#include <cmath>
#include <iostream>
#include <tuple>
#include <unordered_set>
#include "core.h"
#include "definitions.h"
#include "effects/effectsrepository.hpp"
#include "effects/effectstack/model/effectitemmodel.hpp"
#include "effects/effectstack/model/effectstackmodel.hpp"
QString anEffect;
TEST_CASE("Effects groups", "[Effects]")
{
// Create timeline
auto binModel = pCore->projectItemModel();
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
// Here we do some trickery to enable testing.
// We mock the project class so that the undoStack function returns our undoStack
KdenliveDoc document(undoStack);
pCore->projectManager()->testSetDocument(&document);
QDateTime documentDate = QDateTime::currentDateTime();
KdenliveTests::updateTimeline(false, QString(), QString(), documentDate, 0);
auto timeline = document.getTimeline(document.uuid());
pCore->projectManager()->testSetActiveTimeline(timeline);
// Create a request
int tid1;
REQUIRE(timeline->requestTrackInsertion(-1, tid1));
// Create clip
QString binId = KdenliveTests::createProducer(pCore->getProjectProfile(), "red", binModel);
int cid1;
int cid2;
int cid3;
REQUIRE(timeline->requestClipInsertion(binId, tid1, 100, cid1));
REQUIRE(timeline->requestClipInsertion(binId, tid1, 120, cid2));
REQUIRE(timeline->requestClipInsertion(binId, tid1, 140, cid3));
timeline->requestClipsGroup({cid1, cid2, cid3});
std::shared_ptr<ProjectClip> clip = binModel->getClipByBinID(binId);
auto model = clip->getEffectStack();
REQUIRE(model->checkConsistency());
REQUIRE(model->rowCount() == 0);
// Check whether repo works
QVector<QPair<QString, QString>> effects = EffectsRepository::get()->getNames();
REQUIRE(!effects.isEmpty());
anEffect = QStringLiteral("sepia"); // effects.first().first;
REQUIRE(!anEffect.isEmpty());
auto state = [&](int count) {
auto clipModel1 = timeline->getClipEffectStackModel(cid1);
REQUIRE(clipModel1->rowCount() == count);
auto clipModel2 = timeline->getClipEffectStackModel(cid2);
REQUIRE(clipModel2->rowCount() == count);
auto clipModel3 = timeline->getClipEffectStackModel(cid3);
REQUIRE(clipModel3->rowCount() == count);
};
auto effectState = [&](int cid, const QString ¶mName, const QString value) {
auto clipModel1 = timeline->getClipEffectStackModel(cid);
std::shared_ptr<AssetParameterModel> model = clipModel1->getAssetModelById(anEffect);
const QString currentVal = model->getParamFromName(paramName).toString();
if (currentVal.contains(QLatin1Char('='))) {
REQUIRE(currentVal.section(QLatin1Char('='), 1) == value);
} else {
REQUIRE(currentVal == value);
}
};
SECTION("Add an effect to grouped clips")
{
timeline->addClipEffect(cid1, anEffect);
state(1);
undoStack->undo();
state(0);
undoStack->redo();
state(1);
undoStack->undo();
state(0);
}
SECTION("Add an effect to grouped clips, edit param")
{
timeline->addClipEffect(cid1, anEffect);
state(1);
KdenliveSettings::setApplyEffectParamsToGroup(true);
KdenliveSettings::setApplyEffectParamsToGroupWithSameValue(false);
// Apply aan effect param change that should apply to all 3 clips
auto clipModel1 = timeline->getClipEffectStackModel(cid1);
std::shared_ptr<AssetParameterModel> model = clipModel1->getAssetModelById(anEffect);
QModelIndex ix = model->getParamIndexFromName(QStringLiteral("u"));
auto *command = new AssetCommand(model, ix, QStringLiteral("140"));
pCore->groupAssetCommand(model->getOwnerId(), model->getAssetId(), ix, QString::number(75), QString::number(140), command);
pCore->pushUndo(command);
// Check that the param change was done on all effects in the group
effectState(cid1, QStringLiteral("u"), QStringLiteral("140"));
effectState(cid2, QStringLiteral("u"), QStringLiteral("140"));
effectState(cid3, QStringLiteral("u"), QStringLiteral("140"));
undoStack->undo();
effectState(cid1, QStringLiteral("u"), QStringLiteral("75"));
effectState(cid2, QStringLiteral("u"), QStringLiteral("75"));
effectState(cid3, QStringLiteral("u"), QStringLiteral("75"));
undoStack->redo();
effectState(cid1, QStringLiteral("u"), QStringLiteral("140"));
effectState(cid2, QStringLiteral("u"), QStringLiteral("140"));
effectState(cid3, QStringLiteral("u"), QStringLiteral("140"));
KdenliveSettings::setApplyEffectParamsToGroup(false);
// Modify only effect on cid2
auto clipModel2 = timeline->getClipEffectStackModel(cid2);
std::shared_ptr<AssetParameterModel> model2 = clipModel2->getAssetModelById(anEffect);
QModelIndex ix2 = model2->getParamIndexFromName(QStringLiteral("u"));
auto *command2 = new AssetCommand(model2, ix2, QStringLiteral("60"));
pCore->pushUndo(command2);
effectState(cid1, QStringLiteral("u"), QStringLiteral("140"));
effectState(cid2, QStringLiteral("u"), QStringLiteral("60"));
effectState(cid3, QStringLiteral("u"), QStringLiteral("140"));
// Now apply command to group again, cid2 should be left untouched
KdenliveSettings::setApplyEffectParamsToGroup(true);
KdenliveSettings::setApplyEffectParamsToGroupWithSameValue(true);
auto *command3 = new AssetCommand(model, ix, QStringLiteral("180"));
pCore->groupAssetCommand(model->getOwnerId(), model->getAssetId(), ix, QString::number(140), QString::number(180), command3);
pCore->pushUndo(command3);
effectState(cid1, QStringLiteral("u"), QStringLiteral("180"));
effectState(cid2, QStringLiteral("u"), QStringLiteral("60"));
effectState(cid3, QStringLiteral("u"), QStringLiteral("180"));
}
timeline.reset();
clip.reset();
pCore->projectManager()->closeCurrentDocument(false, false);
}
|