Commit 4fc2f242 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle

Merge branch 'refactoring_timeline' into refactoring_track_producers

parents fb9f6c57 a99b4ffd
......@@ -124,7 +124,11 @@ if(NOT RELEASE_BUILD AND EXISTS ${CMAKE_SOURCE_DIR}/.git)
endif()
endif()
include(rttr.CMakeLists.txt)
find_package(RTTR 0.9.6 QUIET)
if(NOT RTTR_FOUND)
message("RTTR not found on system, will download source and build it")
include(rttr.CMakeLists.txt)
endif()
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
......
......@@ -3,7 +3,7 @@
<name>Freeze</name>
<description>Freeze video on a chosen frame</description>
<author>Jean-Baptiste Mardelle</author>
<parameter type="position" name="frame" max="1000000" min="0" default="0">
<parameter type="position" name="frame" max="1000000" min="0" default="0" relative="true">
<name>Freeze at</name>
</parameter>
<parameter type="bool" name="freeze_before" default="0">
......
......@@ -126,6 +126,7 @@ bool isIthParamARef(const rttr::method &method, size_t i)
void fuzz(const std::string &input)
{
Logger::init();
Logger::clear();
std::stringstream ss;
ss << input;
......
......@@ -15,8 +15,8 @@ if(NOT EXISTS "${install_dir}/lib/librttr_core.a")
file(WRITE "${install_dir}/lib/librttr_core.a" "dummy file to be replaced by build")
endif()
add_library(rttr_core STATIC IMPORTED)
add_dependencies(rttr_core rttr_project)
set_target_properties(rttr_core PROPERTIES
add_library(RTTR::Core_Lib STATIC IMPORTED)
add_dependencies(RTTR::Core_Lib rttr_project)
set_target_properties(RTTR::Core_Lib PROPERTIES
IMPORTED_LOCATION "${install_dir}/lib/librttr_core.a"
INTERFACE_INCLUDE_DIRECTORIES "${install_dir}/include")
......@@ -139,8 +139,7 @@ target_link_libraries(kdenliveLib
${CMAKE_DL_LIBS}
${CMAKE_THREAD_LIBS_INIT}
kiss_fft
rttr_core)
add_dependencies(kdenliveLib rttr_project)
RTTR::Core_Lib)
if(BUILD_COVERAGE)
target_link_libraries(kdenliveLib gcov)
......@@ -166,6 +165,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --std=c99")
# Optional deps
if(DRMINGW_FOUND)
target_compile_definitions(kdenlive PRIVATE -DUSE_DRMINGW)
target_include_directories(kdenlive PRIVATE SYSTEM ${DRMINGW_INCLUDE_DIR})
target_link_libraries(kdenlive ${DRMINGW_LIBRARY})
elseif(KF5Crash_FOUND)
target_compile_definitions(kdenlive PRIVATE -DKF5_USE_CRASH)
......
......@@ -208,11 +208,15 @@ void AssetParameterView::refresh(const QModelIndex &topLeft, const QModelIndex &
m_widgets[0]->slotRefresh();
return;
}
Q_ASSERT(bottomRight.row() < (int)m_widgets.size());
for (auto i = (size_t)topLeft.row(); i <= (size_t)bottomRight.row(); ++i) {
if (m_widgets.size() > i) {
m_widgets[i]->slotRefresh();
}
size_t max;
if (!bottomRight.isValid()) {
max = m_widgets.size() - 1;
} else {
max = (size_t) bottomRight.row();
}
Q_ASSERT(max < (int)m_widgets.size());
for (auto i = (size_t)topLeft.row(); i <= max; ++i) {
m_widgets[i]->slotRefresh();
}
}
}
......
......@@ -615,7 +615,7 @@ std::shared_ptr<Mlt::Producer> ProjectClip::getTimelineProducer(int trackId, int
qDebug() << "warp LENGTH before" << warpProducer->get_length();
int original_length = originalProducer()->get_length();
// this is a workaround to cope with Mlt erroneous rounding
warpProducer->set("length", double(original_length) / speed);
warpProducer->set("length", double(original_length) / std::abs(speed));
}
qDebug() << "warp LENGTH" << warpProducer->get_length();
......
......@@ -360,6 +360,7 @@ bool DocumentChecker::hasErrorInClips()
m_ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(m_missingClips.isEmpty() && missingProxies.isEmpty() && missingSources.isEmpty());
max = m_missingClips.count();
m_missingProxyIds.clear();
QStringList processedIds;
for (int i = 0; i < max; ++i) {
QDomElement e = m_missingClips.at(i).toElement();
QString clipType;
......@@ -392,7 +393,11 @@ bool DocumentChecker::hasErrorInClips()
clipType = i18n("Unknown");
type = ClipType::Unknown;
}
QString clipId = e.attribute(QStringLiteral("id")).section(QLatin1Char('_'), 0, 0);
if (processedIds.contains(clipId)) {
continue;
}
processedIds << clipId;
QTreeWidgetItem *item = new QTreeWidgetItem(m_ui.treeWidget, QStringList() << clipType);
item->setData(0, statusRole, CLIPMISSING);
item->setData(0, clipTypeRole, (int)type);
......
......@@ -271,11 +271,10 @@ void Logger::print_trace()
test_file << "ProjectManager &mocked = pmMock.get();" << std::endl;
test_file << "pCore->m_projectManager = &mocked;" << std::endl;
size_t nbrConstructedTimelines = 0;
auto check_consistancy = [&]() {
if (constr.count("TimelineModel") > 0) {
for (size_t i = 0; i < constr["TimelineModel"].size(); ++i) {
test_file << "REQUIRE(timeline_" << i << "->checkConsistency());" << std::endl;
}
for (size_t i = 0; i < nbrConstructedTimelines; ++i) {
test_file << "REQUIRE(timeline_" << i << "->checkConsistency());" << std::endl;
}
};
for (const auto &o : operations) {
......@@ -318,7 +317,6 @@ void Logger::print_trace()
std::cout << "ERROR: unknown method " << invok_name << std::endl;
}
} else if (o.can_convert<Logger::ConstrId>()) {
ConstrId id = o.convert<Logger::ConstrId>();
std::string constr_name = std::string("constr_") + id.type;
......@@ -333,6 +331,7 @@ void Logger::print_trace()
test_file << "auto timeline_" << id.id << " = std::shared_ptr<TimelineItemModel>(&timMock_" << id.id << ".get(), [](...) {});" << std::endl;
test_file << "TimelineItemModel::finishConstruct(timeline_" << id.id << ", guideModel);" << std::endl;
test_file << "Fake(Method(timMock_" << id.id << ", adjustAssetRange));" << std::endl;
nbrConstructedTimelines++;
} else if (id.type == "TrackModel") {
std::string params = process_args(constr[id.type][id.id].second);
test_file << "TrackModel::construct(" << params << ");" << std::endl;
......@@ -363,6 +362,7 @@ void Logger::clear()
is_executing = false;
invoks.clear();
operations.clear();
constr.clear();
}
LogGuard::LogGuard()
......
......@@ -67,6 +67,7 @@ ProjectSettings::ProjectSettings(KdenliveDoc *doc, QMap<QString, QString> metada
: QDialog(parent)
, m_savedProject(savedProject)
, m_lumas(std::move(lumas))
, m_newProject(doc == nullptr)
{
setupUi(this);
tabWidget->setTabBarAutoHide(true);
......@@ -428,7 +429,7 @@ void ProjectSettings::accept()
}
}
}
if (selectedProfile() != pCore->getCurrentProfile()->path()) {
if (!m_newProject && selectedProfile() != pCore->getCurrentProfile()->path()) {
if (KMessageBox::warningContinueCancel(
this,
i18n("Changing the profile of your project cannot be undone.\nIt is recommended to save your project before attempting this operation "
......
......@@ -85,6 +85,7 @@ private:
QStringList m_lumas;
QString m_proxyparameters;
QString m_proxyextension;
bool m_newProject;
/** @brief List of all proxies urls in this project. */
QStringList m_projectProxies;
/** @brief List of all thumbnails used in this project. */
......
set(kdenlive_SRCS
${kdenlive_SRCS}
timeline2/model/builders/meltBuilder.cpp
timeline2/model/clipmodel.cpp
timeline2/model/compositionmodel.cpp
timeline2/model/groupsmodel.cpp
timeline2/model/snapmodel.cpp
timeline2/model/timelinefunctions.cpp
timeline2/model/timelineitemmodel.cpp
timeline2/model/timelinemodel.cpp
timeline2/model/timelinefunctions.cpp
timeline2/model/trackmodel.cpp
timeline2/model/snapmodel.cpp
timeline2/model/builders/meltBuilder.cpp
timeline2/view/dialogs/clipdurationdialog.cpp
timeline2/view/dialogs/spacerdialog.cpp
timeline2/view/dialogs/speeddialog.cpp
timeline2/view/dialogs/trackdialog.cpp
timeline2/view/dialogs/clipdurationdialog.cpp
timeline2/view/previewmanager.cpp
timeline2/view/timelinetabs.cpp
timeline2/view/timelinecontroller.cpp
timeline2/view/timelinewidget.cpp
timeline2/view/qml/timelineitems.cpp
timeline2/view/qmltypes/thumbnailprovider.cpp
timeline2/view/timelinecontroller.cpp
timeline2/view/timelinetabs.cpp
timeline2/view/timelinewidget.cpp
PARENT_SCOPE)
......@@ -371,10 +371,10 @@ void ClipModel::refreshProducerFromBin(PlaylistState::ClipState state, double sp
int out = getOut();
qDebug() << "refresh " << speed << m_speed << in << out;
if (!qFuzzyCompare(speed, m_speed) && !qFuzzyCompare(speed, 0.)) {
in = in * m_speed / speed;
in = in * std::abs(m_speed / speed);
out = in + getPlaytime() - 1;
// prevent going out of the clip's range
out = std::min(out, int(double(m_producer->get_length()) * m_speed / speed) - 1);
out = std::min(out, int(double(m_producer->get_length()) * std::abs(m_speed / speed)) - 1);
m_speed = speed;
qDebug() << "changing speed" << in << out << m_speed;
}
......@@ -408,7 +408,7 @@ bool ClipModel::useTimewarpProducer(double speed, Fun &undo, Fun &redo)
std::function<bool(void)> local_redo = []() { return true; };
double previousSpeed = getSpeed();
int oldDuration = getPlaytime();
int newDuration = int(double(oldDuration) * previousSpeed / speed);
int newDuration = int(double(oldDuration) * std::abs(previousSpeed / speed));
int oldOut = getOut();
int oldIn = getIn();
auto operation = useTimewarpProducer_lambda(speed);
......@@ -639,11 +639,15 @@ QDomElement ClipModel::toXml(QDomDocument &document)
container.setAttribute(QStringLiteral("position"), getPosition());
container.setAttribute(QStringLiteral("state"), (int)m_currentState);
if (auto ptr = m_parent.lock()) {
int trackId = ptr->getTrackPosition(getCurrentTrackId());
int trackId = ptr->getTrackPosition(m_currentTrackId);
container.setAttribute(QStringLiteral("track"), trackId);
if (ptr->isAudioTrack(getCurrentTrackId())) {
container.setAttribute(QStringLiteral("audioTrack"), 1);
container.setAttribute(QStringLiteral("mirrorTrack"), ptr->getTrackPosition(ptr->getMirrorVideoTrackId(getCurrentTrackId())));
int mirrorId = ptr->getMirrorVideoTrackId(m_currentTrackId);
if (mirrorId > -1) {
mirrorId = ptr->getTrackPosition(mirrorId);
}
container.setAttribute(QStringLiteral("mirrorTrack"), mirrorId);
}
}
container.setAttribute(QStringLiteral("speed"), m_speed);
......
......@@ -1247,6 +1247,11 @@ bool TimelineModel::requestGroupMove(int clipId, int groupId, int delta_track, i
{
QWriteLocker locker(&m_lock);
Q_ASSERT(m_allGroups.count(groupId) > 0);
Q_ASSERT(isClip(clipId));
if (getGroupElements(groupId).count(clipId) == 0) {
// this group doesn't contain the clip, abort
return false;
}
bool ok = true;
auto all_items = m_groups->getLeaves(groupId);
Q_ASSERT(all_items.size() > 1);
......@@ -1370,6 +1375,10 @@ bool TimelineModel::requestGroupDeletion(int clipId, bool logUndo)
{
QWriteLocker locker(&m_lock);
TRACE(clipId, logUndo);
if (!m_groups->isInGroup(clipId)) {
TRACE_RES(false);
return false;
}
Fun undo = []() { return true; };
Fun redo = []() { return true; };
bool res = requestGroupDeletion(clipId, undo, redo);
......
#include "speeddialog.h"
#include "ui_speeddialog_ui.h"
SpeedDialog::SpeedDialog(QWidget *parent, double speed, double minSpeed, double maxSpeed, bool reversed)
: QDialog(parent)
, ui(new Ui::SpeedDialog)
{
ui->setupUi(this);
setWindowTitle(i18n("Clip Speed"));
ui->doubleSpinBox->setDecimals(2);
ui->doubleSpinBox->setMinimum(minSpeed);
ui->doubleSpinBox->setMaximum(maxSpeed);
ui->doubleSpinBox->setValue(speed);
if (reversed) {
ui->checkBox->setChecked(true);
}
}
SpeedDialog::~SpeedDialog()
{
delete ui;
}
double SpeedDialog::getValue() const
{
double val = ui->doubleSpinBox->value();
if (ui->checkBox->checkState() == Qt::Checked) {
val *= -1;
}
return val;
}
#ifndef SPEEDDIALOG_H
#define SPEEDDIALOG_H
#include <QDialog>
namespace Ui {
class SpeedDialog;
}
class SpeedDialog : public QDialog
{
Q_OBJECT
public:
explicit SpeedDialog(QWidget *parent, double speed, double minSpeed, double maxSpeed, bool reversed);
~SpeedDialog();
double getValue() const;
private:
Ui::SpeedDialog *ui;
};
#endif // SPEEDDIALOG_H
......@@ -54,8 +54,8 @@ Row {
isFirstChunk: index == 0
showItem: waveform.visible && (index * width) < waveform.scrollEnd && (index * width + width) > waveform.scrollStart
format: timeline.audioThumbFormat
inPoint: Math.round((clipRoot.inPoint + (index * waveform.maxWidth / clipRoot.timeScale)) * clipRoot.speed) * channels
outPoint: inPoint + Math.round(width / clipRoot.timeScale * clipRoot.speed) * channels
inPoint: Math.round((clipRoot.inPoint + (index * waveform.maxWidth / clipRoot.timeScale)) * Math.abs(clipRoot.speed)) * channels
outPoint: inPoint + Math.round(width / clipRoot.timeScale * Math.abs(clipRoot.speed)) * channels
levels: clipRoot.audioLevels
fillColor: activePalette.text
}
......
......@@ -29,6 +29,7 @@
#include "bin/projectitemmodel.h"
#include "core.h"
#include "dialogs/spacerdialog.h"
#include "dialogs/speeddialog.h"
#include "doc/kdenlivedoc.h"
#include "effects/effectsrepository.hpp"
#include "effects/effectstack/model/effectstackmodel.hpp"
......@@ -610,7 +611,10 @@ void TimelineController::copyItem()
if (audioCopy) {
int masterMirror = m_model->getMirrorVideoTrackId(masterTid);
if (masterMirror == -1) {
container.setAttribute(QStringLiteral("audioCopy"), 1);
QPair<QList <int>, QList <int> > projectTracks = TimelineFunctions::getAVTracksIds(m_model);
if (!projectTracks.second.isEmpty()) {
masterTrack = m_model->getTrackPosition(projectTracks.second.first());
}
} else {
masterTrack = m_model->getTrackPosition(masterMirror);
}
......@@ -657,7 +661,6 @@ bool TimelineController::pasteItem()
QMap<QString, QString> mappedIds;
// Check available tracks
QPair<QList <int>, QList <int> > projectTracks = TimelineFunctions::getAVTracksIds(m_model);
bool masterIsAudio = copiedItems.documentElement().hasAttribute(QStringLiteral("audioCopy"));
int masterSourceTrack = copiedItems.documentElement().attribute(QStringLiteral("masterTrack")).toInt();
QDomNodeList clips = copiedItems.documentElement().elementsByTagName(QStringLiteral("clip"));
QDomNodeList compositions = copiedItems.documentElement().elementsByTagName(QStringLiteral("composition"));
......@@ -723,6 +726,7 @@ bool TimelineController::pasteItem()
// Check we have enough tracks above/below
if (requestedVideoTracks > 0) {
qDebug()<<"MASTERSTK: "<<masterSourceTrack<<", VTKS: "<<videoTracks;
int tracksBelow = masterSourceTrack - videoTracks.first();
int tracksAbove = videoTracks.last() - masterSourceTrack;
qDebug()<<"// RQST TKS BELOW: "<<tracksBelow<<" / ABOVE: "<<tracksAbove;
......@@ -747,17 +751,17 @@ bool TimelineController::pasteItem()
tracksMap.insert(tk, projectTracks.second.at(masterIx + tk - masterSourceTrack));
qDebug()<<"// TK MAP: "<<tk<<" => "<<projectTracks.second.at(masterIx + tk - masterSourceTrack);
}
QMapIterator<int, int> i(audioMirrors);
while (i.hasNext()) {
i.next();
int videoIx = tracksMap.value(i.value());
qDebug()<<"// TK AUDIO MAP: "<<i.key()<<" => "<<videoIx<<" ; AUDIO MIRROR: "<<m_model->getMirrorAudioTrackId(videoIx);
tracksMap.insert(i.key(), m_model->getMirrorAudioTrackId(videoIx));
QMapIterator<int, int> it(audioMirrors);
while (it.hasNext()) {
it.next();
int videoIx = tracksMap.value(it.value());
//qDebug()<<"// TK AUDIO MAP: "<<it.key()<<" => "<<videoIx<<" ; AUDIO MIRROR: "<<m_model->getMirrorAudioTrackId(videoIx);
tracksMap.insert(it.key(), m_model->getMirrorAudioTrackId(videoIx));
}
qDebug()<<"++++++++++++++++++++++++++\n\n\n// AUDIO MIRRORS: "<<audioMirrors<<", RESULT: "<<tracksMap;
for (int tk : singleAudioTracks) {
//TODO
for (int i = 0; i < singleAudioTracks.size(); i++) {
tracksMap.insert(singleAudioTracks.at(i), projectTracks.first.at(i));
}
qDebug()<<"++++++++++++++++++++++++++\n\n\n// AUDIO MIRRORS: "<<audioMirrors<<", RESULT: "<<tracksMap;
if (!docId.isEmpty() && docId != pCore->currentDoc()->getDocumentProperty(QStringLiteral("documentid"))) {
// paste from another document, import bin clips
QString folderId = pCore->projectItemModel()->getFolderIdByName(i18n("Pasted clips"));
......@@ -1748,10 +1752,13 @@ void TimelineController::changeItemSpeed(int clipId, double speed)
minSpeed = std::max(minSpeed, minSpeed2);
maxSpeed = std::min(maxSpeed, maxSpeed2);
}
speed = QInputDialog::getDouble(QApplication::activeWindow(), i18n("Clip Speed"), i18n("Percentage"), speed, minSpeed, maxSpeed, 2, &ok);
if (!ok) {
// speed = QInputDialog::getDouble(QApplication::activeWindow(), i18n("Clip Speed"), i18n("Percentage"), speed, minSpeed, maxSpeed, 2, &ok);
QScopedPointer<SpeedDialog> d(new SpeedDialog(QApplication::activeWindow(), std::abs(speed), minSpeed, maxSpeed, speed < 0));
if (d->exec() != QDialog::Accepted) {
return;
}
speed = d->getValue();
qDebug() << "requesting speed " << speed;
}
m_model->requestClipTimeWarp(clipId, speed);
}
......
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SpeedDialog</class>
<widget class="QDialog" name="SpeedDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>399</width>
<height>309</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>30</x>
<y>240</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QWidget" name="gridLayoutWidget">
<property name="geometry">
<rect>
<x>40</x>
<y>40</y>
<width>326</width>
<height>171</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Speed</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox"/>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Reverse clip</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SpeedDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SpeedDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
......@@ -684,3 +684,205 @@ TEST_CASE("FuzzBug3")
}
pCore->m_projectManager = nullptr;
}
TEST_CASE("FuzzBug4")
{
auto binModel = pCore->projectItemModel();
binModel->clean();
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack);
TimelineModel::next_id = 0;
{
Mock<ProjectManager> pmMock;
When(Method(pmMock, undoStack)).AlwaysReturn(undoStack);
ProjectManager &mocked = pmMock.get();
pCore->m_projectManager = &mocked;
TimelineItemModel tim_0(&reg_profile, undoStack);
Mock<TimelineItemModel> timMock_0(tim_0);
auto timeline_0 = std::shared_ptr<TimelineItemModel>(&timMock_0.get(), [](...) {});
TimelineItemModel::finishConstruct(timeline_0, guideModel);
Fake(Method(timMock_0, adjustAssetRange));
REQUIRE(timeline_0->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
createProducer(reg_profile, "red", binModel, 2, true);
REQUIRE(timeline_0->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
createProducer(reg_profile, "blue", binModel, 20, true);
REQUIRE(timeline_0->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
createProducer(reg_profile, "gseen", binModel, 20, true);
REQUIRE(timeline_0->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
TrackModel::construct(timeline_0, -1, -1, "", false);
REQUIRE(timeline_0->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
createProducerWithSound(reg_profile, binModel);
REQUIRE(timeline_0->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
{
int dummy_3;
bool res = timeline_0->requestClipInsertion("5", 1, 3, dummy_3, true, true, true);
REQUIRE(res == true);
}
REQUIRE(timeline_0->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
{
bool res = timeline_0->requestGroupDeletion(2, false);
}
REQUIRE(timeline_0->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
}
pCore->m_projectManager = nullptr;
}
TEST_CASE("FuzzBug5")
{
auto binModel = pCore->projectItemModel();
binModel->clean();
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack);
TimelineModel::next_id = 0;
{
Mock<ProjectManager> pmMock;
When(Method(pmMock, undoStack)).AlwaysReturn(undoStack);
ProjectManager &mocked = pmMock.get();
pCore->m_projectManager = &mocked;
TimelineItemModel tim_0(&reg_profile, undoStack);
Mock<TimelineItemModel> timMock_0(tim_0);
auto timeline_0 = std::shared_ptr<TimelineItemModel>(&timMock_0.get(), [](...) {});
TimelineItemModel::finishConstruct(timeline_0, guideModel);
Fake(Method(timMock_0, adjustAssetRange));
REQUIRE(timeline_0->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
TrackModel::construct(timeline_0, -1, 0, "", false);
REQUIRE(timeline_0->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
TimelineItemModel tim_1(&reg_profile, undoStack);
Mock<TimelineItemModel> timMock_1(tim_1);
auto timeline_1 = std::shared_ptr<TimelineItemModel>(&timMock_1.get(), [](...) {});
TimelineItemModel::finishConstruct(timeline_1, guideModel);
Fake(Method(timMock_1, adjustAssetRange));
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
TrackModel::construct(timeline_0, -1, 0, "$", false);
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
TrackModel::construct(timeline_1, -1, 0, "$", true);
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
createProducerWithSound(reg_profile, binModel);
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
TrackModel::construct(timeline_1, -1, -1, "$", false);
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
TrackModel::construct(timeline_1, -1, -1, "$", true);
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
{
int dummy_3;
bool res = timeline_1->requestClipInsertion("2", 5, 0, dummy_3, true, false, true);
REQUIRE(res == true);
}
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
undoStack->redo();
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
{
int dummy_3;
bool res = timeline_1->requestClipInsertion("2", 6, 20, dummy_3, true, false, true);
REQUIRE(res == true);
}
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());
undoStack->undo();
REQUIRE(timeline_0->checkConsistency());
REQUIRE(timeline_1->checkConsistency());