Commit 8918134c authored by Nicolas Carion's avatar Nicolas Carion
Browse files

Fix insert zone breaking groups + tests

parent 8c951668
......@@ -612,7 +612,7 @@ std::shared_ptr<Mlt::Producer> ProjectClip::getTimelineProducer(int trackId, int
resource = m_service;
}
QString url = QString("timewarp:%1:%2").arg(locale.toString(speed)).arg(resource);
warpProducer.reset(new Mlt::Producer(*originalProducer()->profile(), url.toUtf8().constData()));
warpProducer.reset(new Mlt::Producer(originalProducer()->get_profile(), url.toUtf8().constData()));
qDebug() << "new producer: " << url;
qDebug() << "warp LENGTH before" << warpProducer->get_length();
int original_length = originalProducer()->get_length();
......
......@@ -138,7 +138,7 @@ void ClipController::addMasterProducer(const std::shared_ptr<Mlt::Producer> &pro
namespace {
QString producerXml(const std::shared_ptr<Mlt::Producer> &producer, bool includeMeta)
{
Mlt::Consumer c(*producer->profile(), "xml", "string");
Mlt::Consumer c(producer->get_profile(), "xml", "string");
Mlt::Service s(producer->get_service());
if (!s.is_valid()) {
return QString();
......
......@@ -305,7 +305,7 @@ bool TimelineFunctions::insertZone(const std::shared_ptr<TimelineItemModel> &tim
++it;
continue;
}
result = TimelineFunctions::liftZone(timeline, target_track, QPoint(insertFrame, insertFrame + (zone.y() - zone.x())), undo, redo);
result = result && TimelineFunctions::liftZone(timeline, target_track, QPoint(insertFrame, insertFrame + (zone.y() - zone.x())), undo, redo);
if (!result) {
break;
}
......@@ -323,11 +323,11 @@ bool TimelineFunctions::insertZone(const std::shared_ptr<TimelineItemModel> &tim
int startClipId = timeline->getClipByPosition(target_track, insertFrame);
if (startClipId > -1) {
// There is a clip, cut it
TimelineFunctions::requestClipCut(timeline, startClipId, insertFrame, undo, redo);
result = result && TimelineFunctions::requestClipCut(timeline, startClipId, insertFrame, undo, redo);
}
++it;
}
result = TimelineFunctions::insertSpace(timeline, trackId, QPoint(insertFrame, insertFrame + (zone.y() - zone.x())), undo, redo);
result = result && TimelineFunctions::requestInsertSpace(timeline, QPoint(insertFrame, insertFrame + (zone.y() - zone.x())), undo, redo);
}
if (result) {
int newId = -1;
......@@ -399,30 +399,38 @@ bool TimelineFunctions::removeSpace(const std::shared_ptr<TimelineItemModel> &ti
return result;
}
bool TimelineFunctions::insertSpace(const std::shared_ptr<TimelineItemModel> &timeline, int trackId, QPoint zone, Fun &undo, Fun &redo)
bool TimelineFunctions::requestInsertSpace(const std::shared_ptr<TimelineItemModel> &timeline, QPoint zone, Fun &undo, Fun &redo)
{
Q_UNUSED(trackId)
std::unordered_set<int> clips = timeline->getItemsInRange(-1, zone.x(), -1, true);
timeline->requestClearSelection();
Fun local_undo = []() { return true; };
Fun local_redo = []() { return true; };
std::unordered_set<int> items = timeline->getItemsInRange(-1, zone.x(), -1, true);
if (items.empty()) {
return true;
}
timeline->requestSetSelection(items);
bool result = true;
if (!clips.empty()) {
int clipId = *clips.begin();
if (clips.size() > 1) {
int res = timeline->requestClipsGroup(clips, undo, redo);
if (res > -1) {
result = timeline->requestGroupMove(clipId, res, 0, zone.y() - zone.x(), true, true, undo, redo);
if (result) {
result = timeline->requestClipUngroup(clipId, undo, redo);
} else {
pCore->displayMessage(i18n("Cannot move selected group"), ErrorMessage);
}
}
} else {
// only 1 clip to be moved
int clipStart = timeline->getItemPosition(clipId);
result = timeline->requestClipMove(clipId, timeline->getItemTrackId(clipId), clipStart + (zone.y() - zone.x()), true, true, undo, redo);
}
int itemId = *(items.begin());
int targetTrackId = timeline->getItemTrackId(itemId);
int targetPos = timeline->getItemPosition(itemId) + zone.y() - zone.x();
// TODO the three move functions should be unified in a "requestItemMove" function
if (timeline->m_groups->isInGroup(itemId)) {
result =
result && timeline->requestGroupMove(itemId, timeline->m_groups->getRootId(itemId), 0, zone.y() - zone.x(), true, true, local_undo, local_redo);
} else if (timeline->isClip(itemId)) {
result = result && timeline->requestClipMove(itemId, targetTrackId, targetPos, true, true, local_undo, local_redo);
} else {
result = result && timeline->requestCompositionMove(itemId, targetTrackId, timeline->m_allCompositions[itemId]->getForcedTrack(), targetPos, true, true,
local_undo, local_redo);
}
timeline->requestClearSelection();
if (!result) {
bool undone = local_undo();
Q_ASSERT(undone);
pCore->displayMessage(i18n("Cannot move selected group"), ErrorMessage);
}
UPDATE_UNDO_REDO_NOLOCK(local_redo, local_undo, undo, redo);
return result;
}
......
......@@ -84,7 +84,11 @@ struct TimelineFunctions
static bool extractZone(const std::shared_ptr<TimelineItemModel> &timeline, QVector<int> tracks, QPoint zone, bool liftOnly);
static bool liftZone(const std::shared_ptr<TimelineItemModel> &timeline, int trackId, QPoint zone, Fun &undo, Fun &redo);
static bool removeSpace(const std::shared_ptr<TimelineItemModel> &timeline, int trackId, QPoint zone, Fun &undo, Fun &redo);
static bool insertSpace(const std::shared_ptr<TimelineItemModel> &timeline, int trackId, QPoint zone, Fun &undo, Fun &redo);
/** @brief This function will insert a blank space starting at zone.x, and ending at zone.y. This will affect all the tracks
@returns true on success, false otherwise
*/
static bool requestInsertSpace(const std::shared_ptr<TimelineItemModel> &timeline, QPoint zone, Fun &undo, Fun &redo);
static bool insertZone(const std::shared_ptr<TimelineItemModel> &timeline, QList<int> trackIds, const QString &binId, int insertFrame, QPoint zone,
bool overwrite);
......
......@@ -1459,7 +1459,7 @@ void TimelineController::addCompositionToClip(const QString &assetId, int clipId
void TimelineController::addEffectToClip(const QString &assetId, int clipId)
{
qDebug()<<"/// ADDING ASSET: "<<assetId;
qDebug() << "/// ADDING ASSET: " << assetId;
m_model->addClipEffect(clipId, assetId);
}
......@@ -1924,7 +1924,7 @@ bool TimelineController::endFakeMove(int clipId, int position, bool updateView,
// There is a clip, cut
res = res && TimelineFunctions::requestClipCut(m_model, startClipId, position, undo, redo);
}
res = res && TimelineFunctions::insertSpace(m_model, trackId, QPoint(position, position + duration), undo, redo);
res = res && TimelineFunctions::requestInsertSpace(m_model, QPoint(position, position + duration), undo, redo);
}
res = res && m_model->getTrackById(trackId)->requestClipInsertion(clipId, position, updateView, invalidateTimeline, undo, redo);
if (res) {
......@@ -2038,7 +2038,7 @@ bool TimelineController::endFakeGroupMove(int clipId, int groupId, int delta_tra
res = res && TimelineFunctions::requestClipCut(m_model, startClipId, target_position, undo, redo);
}
}
res = res && TimelineFunctions::insertSpace(m_model, -1, QPoint(min, max), undo, redo);
res = res && TimelineFunctions::requestInsertSpace(m_model, QPoint(min, max), undo, redo);
}
for (int item : sorted_clips) {
if (m_model->isClip(item)) {
......@@ -2125,8 +2125,8 @@ void TimelineController::updateEffectKeyframe(int cid, int oldFrame, int newFram
bool TimelineController::darkBackground() const
{
KColorScheme scheme(QApplication::palette().currentColorGroup());
return scheme.background(KColorScheme::NormalBackground).color().value() < 0.5;
KColorScheme scheme(QApplication::palette().currentColorGroup());
return scheme.background(KColorScheme::NormalBackground).color().value() < 0.5;
}
QColor TimelineController::videoColor() const
......@@ -2171,7 +2171,9 @@ void TimelineController::switchRecording(int trackId)
} else {
m_recordStart.second = maximumSpace - m_recordStart.first;
if (m_recordStart.second < 8) {
pCore->displayMessage(i18n("Impossible to capture here: the capture could override clips. Please remove clips after the current position or choose a different track"), ErrorMessage, 500);
pCore->displayMessage(i18n("Impossible to capture here: the capture could override clips. Please remove clips after the current position or "
"choose a different track"),
ErrorMessage, 500);
return;
}
}
......@@ -2189,7 +2191,7 @@ void TimelineController::switchRecording(int trackId)
Fun redo = []() { return true; };
std::function<void(const QString &)> callBack = [this, trackId](const QString &binId) {
int id = -1;
qDebug() << "callback " << binId << " " << trackId<<", MAXIMUM SPACE: "<<m_recordStart.second;
qDebug() << "callback " << binId << " " << trackId << ", MAXIMUM SPACE: " << m_recordStart.second;
bool res = false;
if (m_recordStart.second > 0) {
// Limited space on track
......@@ -2199,8 +2201,8 @@ void TimelineController::switchRecording(int trackId)
res = m_model->requestClipInsertion(binId, trackId, m_recordStart.first, id, true, true, false);
}
};
QString binId = ClipCreator::createClipFromFile(recordedFile,
pCore->projectItemModel()->getRootFolder()->clipId(), pCore->projectItemModel(), undo, redo, callBack);
QString binId = ClipCreator::createClipFromFile(recordedFile, pCore->projectItemModel()->getRootFolder()->clipId(), pCore->projectItemModel(), undo,
redo, callBack);
if (binId != QStringLiteral("-1")) {
pCore->pushUndo(undo, redo, i18n("Record audio"));
}
......
......@@ -522,7 +522,7 @@ TEST_CASE("Advanced trimming operations", "[Trimming]")
Logger::print_trace();
}
TEST_CASE("Insert/delete spaces", "[Trimming2]")
TEST_CASE("Insert/delete", "[Trimming2]")
{
Logger::clear();
auto binModel = pCore->projectItemModel();
......@@ -588,6 +588,85 @@ TEST_CASE("Insert/delete spaces", "[Trimming2]")
state(0);
}
SECTION("Insert zone should preserve groups")
{
int cid1 = -1;
REQUIRE(timeline->requestClipInsertion(binId, tid1, 3, cid1, true, true, false));
int cid2 = timeline->m_groups->getSplitPartner(cid1);
int l = timeline->getClipPlaytime(cid2);
auto state = [&]() {
REQUIRE(timeline->checkConsistency());
REQUIRE(timeline->getTrackClipsCount(tid1) == 1);
REQUIRE(timeline->getTrackClipsCount(tid2) == 1);
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
REQUIRE(timeline->getClipTrackId(cid2) == tid2);
REQUIRE(timeline->getClipPosition(cid1) == 3);
REQUIRE(timeline->getClipPosition(cid2) == 3);
REQUIRE(timeline->getClipPtr(cid1)->clipState() == PlaylistState::VideoOnly);
REQUIRE(timeline->getClipPtr(cid2)->clipState() == PlaylistState::AudioOnly);
// we check that the av group was correctly created
REQUIRE(timeline->getGroupElements(cid1) == std::unordered_set<int>({cid1, cid2}));
int g1 = timeline->m_groups->getDirectAncestor(cid1);
REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({cid1, cid2}));
REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit);
};
state();
REQUIRE(TimelineFunctions::insertZone(timeline, {tid1, tid2}, binId, 3 + 2, {l / 4, 3 * l / 4}, false));
int small_length = 3 * l / 4 - l / 4;
int cid3 = timeline->getClipByPosition(tid1, 3 + 2);
int cid4 = timeline->getClipByPosition(tid2, 3 + 2);
int cid5 = timeline->getClipByPosition(tid1, 3 + 2 + small_length);
int cid6 = timeline->getClipByPosition(tid2, 3 + 2 + small_length);
auto state2 = [&]() {
REQUIRE(timeline->checkConsistency());
REQUIRE(timeline->getTrackClipsCount(tid1) == 3);
REQUIRE(timeline->getTrackClipsCount(tid2) == 3);
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
REQUIRE(timeline->getClipTrackId(cid2) == tid2);
REQUIRE(timeline->getClipTrackId(cid3) == tid1);
REQUIRE(timeline->getClipTrackId(cid4) == tid2);
REQUIRE(timeline->getClipTrackId(cid5) == tid1);
REQUIRE(timeline->getClipTrackId(cid6) == tid2);
REQUIRE(timeline->getClipPosition(cid1) == 3);
REQUIRE(timeline->getClipPosition(cid2) == 3);
REQUIRE(timeline->getClipPosition(cid3) == 3 + 2);
REQUIRE(timeline->getClipPosition(cid4) == 3 + 2);
REQUIRE(timeline->getClipPosition(cid5) == 3 + 2 + small_length);
REQUIRE(timeline->getClipPosition(cid6) == 3 + 2 + small_length);
REQUIRE(timeline->getClipPlaytime(cid1) + timeline->getClipPlaytime(cid5) == l);
REQUIRE(timeline->getClipPlaytime(cid1) == 2);
REQUIRE(timeline->getClipPlaytime(cid3) == small_length);
REQUIRE(timeline->getClipPtr(cid1)->clipState() == PlaylistState::VideoOnly);
REQUIRE(timeline->getClipPtr(cid2)->clipState() == PlaylistState::AudioOnly);
REQUIRE(timeline->getClipPtr(cid3)->clipState() == PlaylistState::VideoOnly);
REQUIRE(timeline->getClipPtr(cid4)->clipState() == PlaylistState::AudioOnly);
REQUIRE(timeline->getClipPtr(cid5)->clipState() == PlaylistState::VideoOnly);
REQUIRE(timeline->getClipPtr(cid6)->clipState() == PlaylistState::AudioOnly);
// we check that the av group was correctly created
REQUIRE(timeline->getGroupElements(cid1) == std::unordered_set<int>({cid1, cid2}));
int g1 = timeline->m_groups->getDirectAncestor(cid1);
REQUIRE(timeline->m_groups->getDirectChildren(g1) == std::unordered_set<int>({cid1, cid2}));
REQUIRE(timeline->m_groups->getType(g1) == GroupType::AVSplit);
REQUIRE(timeline->getGroupElements(cid3) == std::unordered_set<int>({cid3, cid4}));
int g2 = timeline->m_groups->getDirectAncestor(cid3);
REQUIRE(timeline->m_groups->getDirectChildren(g2) == std::unordered_set<int>({cid3, cid4}));
REQUIRE(timeline->m_groups->getType(g2) == GroupType::AVSplit);
int g3 = timeline->m_groups->getDirectAncestor(cid5);
REQUIRE(timeline->m_groups->getDirectChildren(g3) == std::unordered_set<int>({cid5, cid6}));
REQUIRE(timeline->m_groups->getType(g3) == GroupType::AVSplit);
};
state2();
undoStack->undo();
state();
undoStack->redo();
state2();
}
binModel->clean();
pCore->m_projectManager = nullptr;
Logger::print_trace();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment