aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Baptiste Mardelle <[email protected]>2016-05-21 21:29:22 +0200
committerJean-Baptiste Mardelle <[email protected]>2016-05-21 21:29:22 +0200
commit1799b44b560cb7dc4fb4737ed28de96f8b7eaead (patch)
treee7449d375c896e3261553febf09b4202e7c2a9a3
parent91b043103e88af3408f07681fee6ae080d1a62b9 (diff)
Fix a few bugs in timeline preview, add support for undo (only 1 step supported)
Ref: T1949
-rw-r--r--src/doc/kdenlivedoc.cpp49
-rw-r--r--src/doc/kdenlivedoc.h9
-rw-r--r--src/kdenlivesettings.kcfg14
-rw-r--r--src/mainwindow.cpp11
-rw-r--r--src/timeline/customruler.cpp5
-rw-r--r--src/timeline/customruler.h2
-rw-r--r--src/timeline/timeline.cpp54
-rw-r--r--src/timeline/timeline.h4
8 files changed, 110 insertions, 38 deletions
diff --git a/src/doc/kdenlivedoc.cpp b/src/doc/kdenlivedoc.cpp
index bdac317..729d99a 100644
--- a/src/doc/kdenlivedoc.cpp
+++ b/src/doc/kdenlivedoc.cpp
@@ -82,7 +82,8 @@ KdenliveDoc::KdenliveDoc(const QUrl &url, const QUrl &projectFolder, QUndoGroup
m_notesWidget(notes->widget()),
m_commandStack(new QUndoStack(undoGroup)),
m_modified(false),
- m_projectFolder(projectFolder)
+ m_projectFolder(projectFolder),
+ m_undoPreviewIndex(-1)
{
// init m_profile struct
m_profile.frame_rate_num = 0;
@@ -98,7 +99,7 @@ KdenliveDoc::KdenliveDoc(const QUrl &url, const QUrl &projectFolder, QUndoGroup
m_clipManager = new ClipManager(this);
connect(m_clipManager, SIGNAL(displayMessage(QString,int)), parent, SLOT(slotGotProgressInfo(QString,int)));
bool success = false;
- connect(m_commandStack, SIGNAL(indexChanged(int)), this, SLOT(slotModified()));
+ connect(m_commandStack, SIGNAL(indexChanged(int)), this, SLOT(slotModified(int)));
connect(m_render, SIGNAL(setDocumentNotes(QString)), this, SLOT(slotSetDocumentNotes(QString)));
connect(pCore->producerQueue(), &ProducerQueue::switchProfile, this, &KdenliveDoc::switchProfile);
//connect(m_commandStack, SIGNAL(cleanChanged(bool)), this, SLOT(setModified(bool)));
@@ -844,9 +845,15 @@ void KdenliveDoc::setUrl(const QUrl &url)
m_url = url;
}
-void KdenliveDoc::slotModified()
+void KdenliveDoc::slotModified(int ix)
{
setModified(m_commandStack->isClean() == false);
+ if (m_undoPreviewIndex != -1 && ix == m_undoPreviewIndex - 1) {
+ restoreTimelinePreviews();
+ } else if (ix < m_undoPreviewIndex - 1) {
+ // Restore preview files if any
+ m_undoPreviewIndex = -1;
+ }
}
void KdenliveDoc::setModified(bool mod)
@@ -1605,13 +1612,47 @@ void KdenliveDoc::doAddAction(const QString &name, QAction *a)
void KdenliveDoc::invalidatePreviews(QList <int> chunks)
{
QDir dir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
+ bool redo = true;
+ if (m_commandStack->index() > m_undoPreviewIndex) {
+ m_undoPreviewIndex = m_commandStack->index();
+ } else {
+ redo = false;
+ }
+ m_undoChunks = chunks;
+ // Clear all previous undo files
+ if (redo && dir.cd("undo")) {
+ dir.removeRecursively();
+ dir.cdUp();
+ }
+ dir.mkdir("undo");
QString documentId = m_documentProperties.value(QStringLiteral("documentid"));
+ QString ext = m_documentProperties.value(QStringLiteral("previewextension"));
foreach(int i, chunks) {
- QFile::remove(dir.absoluteFilePath(documentId + QString("-%1.%2").arg(i).arg(KdenliveSettings::tl_extension())));
+ QString current = documentId + QString("-%1.%2").arg(i).arg(ext);
+ if (redo)
+ dir.rename(current, "undo/" + current);
+ else
+ dir.remove(current);
}
setModified(true);
}
+void KdenliveDoc::restoreTimelinePreviews()
+{
+ QDir dir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
+ QString documentId = m_documentProperties.value(QStringLiteral("documentid"));
+ QString ext = m_documentProperties.value(QStringLiteral("previewextension"));
+ foreach(int i, m_undoChunks) {
+ QString current = documentId + QString("-%1.%2").arg(i).arg(ext);
+ dir.remove(current);
+ dir.rename("undo/" + current, current);
+ }
+ dir.rmdir("undo");
+ emit reloadChunks(m_undoChunks);
+ m_undoPreviewIndex = -1;
+ m_undoChunks.clear();
+}
+
void KdenliveDoc::previewProgress(int p)
{
pCore->window()->setPreviewProgress(p);
diff --git a/src/doc/kdenlivedoc.h b/src/doc/kdenlivedoc.h
index 41b8c16..0607ffe 100644
--- a/src/doc/kdenlivedoc.h
+++ b/src/doc/kdenlivedoc.h
@@ -185,6 +185,8 @@ private:
/** @brief The project folder, used to store project files (titles, effects...). */
QUrl m_projectFolder;
+ int m_undoPreviewIndex;
+ QList <int> m_undoChunks;
QMap <QString, QString> m_documentProperties;
QMap <QString, QString> m_documentMetadata;
@@ -203,6 +205,8 @@ private:
void loadDocumentProperties();
/** @brief update document properties to reflect a change in the current profile */
void updateProjectProfile(bool reloadProducers = false);
+ /** @brief Undo stack changed, restore timeline preview files if any*/
+ void restoreTimelinePreviews();
public slots:
void slotCreateTextTemplateClip(const QString &group, const QString &groupId, QUrl path);
@@ -221,7 +225,7 @@ private slots:
void slotClipModified(const QString &path);
void slotClipMissing(const QString &path);
void slotProcessModifiedClips();
- void slotModified();
+ void slotModified(int ix);
void slotSetDocumentNotes(const QString &notes);
void switchProfile(MltVideoProfile profile, const QString &id, const QDomElement &xml);
void slotSwitchProfile();
@@ -244,6 +248,9 @@ signals:
void reloadEffects();
/** @brief Fps was changed, update timeline */
void updateFps(bool changed);
+ /** @brief Some timeline preview chunks restored, reload them */
+ void reloadChunks(QList <int> chunks);
+
};
#endif
diff --git a/src/kdenlivesettings.kcfg b/src/kdenlivesettings.kcfg
index 3f19453..1c4d1b4 100644
--- a/src/kdenlivesettings.kcfg
+++ b/src/kdenlivesettings.kcfg
@@ -222,20 +222,6 @@
<default>false</default>
</entry>
- <entry name="tl_profile" type="UInt">
- <label>default timeline preview encoding profile.</label>
- <default>0</default>
- </entry>
- <entry name="tl_parameters" type="String">
- <label>Default timeline preview format.</label>
- <default></default>
- </entry>
-
- <entry name="tl_extension" type="String">
- <label>Default timeline preview file extension.</label>
- <default></default>
- </entry>
-
</group>
<group name="sdl">
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index e650f57..136e12a 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -690,17 +690,6 @@ MainWindow::MainWindow(const QString &MltPath, const QUrl &Url, const QString &
KdenliveSettings::setV4l_extension(data.section(';', 1, 1));
}
}
- if (KdenliveSettings::tl_parameters().isEmpty() || KdenliveSettings::tl_extension().isEmpty()) {
- KConfigGroup group(&conf, "timelinepreview");
- QMap< QString, QString > values = group.entryMap();
- QMapIterator<QString, QString> i(values);
- if (i.hasNext()) {
- i.next();
- QString data = i.value();
- KdenliveSettings::setTl_parameters(data.section(';', 0, 0));
- KdenliveSettings::setTl_extension(data.section(';', 1, 1));
- }
- }
if (KdenliveSettings::grab_parameters().isEmpty() || KdenliveSettings::grab_extension().isEmpty()) {
KConfigGroup group(&conf, "screengrab");
QMap< QString, QString > values = group.entryMap();
diff --git a/src/timeline/customruler.cpp b/src/timeline/customruler.cpp
index 8c12144..c7b4d79 100644
--- a/src/timeline/customruler.cpp
+++ b/src/timeline/customruler.cpp
@@ -510,7 +510,7 @@ void CustomRuler::activateZone()
update();
}
-void CustomRuler::updatePreview(int frame, bool rendered)
+void CustomRuler::updatePreview(int frame, bool rendered, bool refresh)
{
if (rendered) {
m_renderingPreviews << frame;
@@ -519,7 +519,8 @@ void CustomRuler::updatePreview(int frame, bool rendered)
m_renderingPreviews.removeAll(frame);
m_dirtyRenderingPreviews << frame;
}
- update(frame * m_factor - offset(), MAX_HEIGHT - 3, KdenliveSettings::timelinechunks() * m_factor + 1, 3);
+ if (refresh)
+ update(frame * m_factor - offset(), MAX_HEIGHT - 3, KdenliveSettings::timelinechunks() * m_factor + 1, 3);
}
const QStringList CustomRuler::previewChunks() const
diff --git a/src/timeline/customruler.h b/src/timeline/customruler.h
index 553b8d5..81db9a1 100644
--- a/src/timeline/customruler.h
+++ b/src/timeline/customruler.h
@@ -50,7 +50,7 @@ public:
void updateProjectFps(const Timecode &t);
void updateFrameSize();
void activateZone();
- void updatePreview(int frame, bool rendered = true);
+ void updatePreview(int frame, bool rendered = true, bool refresh = true);
/** @brief Returns a list of rendered timeline preview chunks */
const QStringList previewChunks() const;
/** @brief Returns a list of dirty timeline preview chunks (that need to be generated) */
diff --git a/src/timeline/timeline.cpp b/src/timeline/timeline.cpp
index 3c57f2a..8666c3c 100644
--- a/src/timeline/timeline.cpp
+++ b/src/timeline/timeline.cpp
@@ -144,9 +144,13 @@ Timeline::Timeline(KdenliveDoc *doc, const QList<QAction *> &actions, const QLis
connect(m_trackview->horizontalScrollBar(), SIGNAL(rangeChanged(int,int)), this, SLOT(slotUpdateVerticalScroll(int,int)));
connect(m_trackview, SIGNAL(mousePosition(int)), this, SIGNAL(mousePosition(int)));
connect(m_doc->renderer(), &Render::previewRender, this, &Timeline::gotPreviewRender);
+ connect(m_doc, &KdenliveDoc::reloadChunks, this, &Timeline::slotReloadChunks);
m_previewTimer.setSingleShot(true);
m_previewTimer.setInterval(3000);
connect(&m_previewTimer, &QTimer::timeout, this, &Timeline::startPreviewRender);
+ m_previewGatherTimer.setSingleShot(true);
+ m_previewGatherTimer.setInterval(200);
+ connect(&m_previewGatherTimer, &QTimer::timeout, this, &Timeline::slotProcessDirtyChunks);
}
Timeline::~Timeline()
@@ -1759,11 +1763,12 @@ void Timeline::gotPreviewRender(int frame, const QString &file, int progress)
if (trackPlaylist.is_blank_at(frame)) {
Mlt::Producer prod(*m_tractor->profile(), 0, file.toUtf8().constData());
if (prod.is_valid()) {
- m_ruler->updatePreview(frame);
+ m_ruler->updatePreview(frame, true, true);
prod.set("mlt_service", "avformat-novalidate");
trackPlaylist.insert_at(frame, &prod, 1);
}
}
+ trackPlaylist.consolidate_blanks();
m_tractor->unlock();
m_doc->previewProgress(progress);
m_doc->setModified(true);
@@ -1780,7 +1785,7 @@ void Timeline::addPreviewRange(bool add)
frames << i * chunkSize;
}
m_ruler->addChunks(frames, add);
- if (KdenliveSettings::autopreview())
+ if (add && KdenliveSettings::autopreview())
m_previewTimer.start();
}
@@ -1841,9 +1846,15 @@ void Timeline::invalidatePreview(int startFrame, int endFrame)
delete prod;
m_ruler->updatePreview(i * chunkSize, false);
}
+ m_ruler->update();
trackPlaylist.consolidate_blanks();
m_tractor->unlock();
- m_doc->invalidatePreviews(list);
+ m_previewGatherTimer.start();
+}
+
+void Timeline::slotProcessDirtyChunks()
+{
+ m_doc->invalidatePreviews(m_ruler->getDirtyChunks());
if (KdenliveSettings::autopreview())
m_previewTimer.start();
}
@@ -1853,6 +1864,7 @@ void Timeline::loadPreviewRender()
QString documentId = m_doc->getDocumentProperty(QStringLiteral("documentid"));
QString chunks = m_doc->getDocumentProperty(QStringLiteral("previewchunks"));
QString dirty = m_doc->getDocumentProperty(QStringLiteral("dirtypreviewchunks"));
+ QString ext = m_doc->getDocumentProperty(QStringLiteral("previewextension"));
if (!chunks.isEmpty() || !dirty.isEmpty()) {
if (!m_hasOverlayTrack) {
// Create overlay track
@@ -1863,12 +1875,12 @@ void Timeline::loadPreviewRender()
m_tractor->unlock();
m_hasOverlayTrack = true;
}
- QDir dir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
+ QDir dir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) );
QStringList previewChunks = chunks.split(",", QString::SkipEmptyParts);
QStringList dirtyChunks = dirty.split(",", QString::SkipEmptyParts);
foreach(const QString frame, previewChunks) {
int pos = frame.toInt();
- const QString fileName = dir.absoluteFilePath(documentId + QString("-%1.%2").arg(pos).arg(KdenliveSettings::tl_extension()));
+ const QString fileName = dir.absoluteFilePath(documentId + QString("-%1.%2").arg(pos).arg(ext));
if (QFile::exists(fileName)) {
gotPreviewRender(pos, fileName, 1000);
} else dirtyChunks << frame;
@@ -1877,6 +1889,7 @@ void Timeline::loadPreviewRender()
foreach(const QString i, dirtyChunks) {
m_ruler->updatePreview(i.toInt(), false);
}
+ m_ruler->update();
}
}
}
@@ -1893,3 +1906,34 @@ void Timeline::updatePreviewSettings(const QString &profile)
m_doc->setDocumentProperty(QStringLiteral("previewextension"), ext);
}
}
+
+void Timeline::slotReloadChunks(QList <int> chunks)
+{
+ bool timer = false;
+ if (m_previewTimer.isActive()) {
+ m_previewTimer.stop();
+ timer = true;
+ }
+ QString documentId = m_doc->getDocumentProperty(QStringLiteral("documentid"));
+ QString ext = m_doc->getDocumentProperty(QStringLiteral("previewextension"));
+ QDir dir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
+ Mlt::Producer *overlayTrack = m_tractor->track(tracksCount());
+ m_tractor->lock();
+ Mlt::Playlist trackPlaylist((mlt_playlist) overlayTrack->get_service());
+ delete overlayTrack;
+ foreach(int ix, chunks) {
+ if (trackPlaylist.is_blank_at(ix)) {
+ const QString fileName = dir.absoluteFilePath(documentId + QString("-%1.%2").arg(ix).arg(ext));
+ Mlt::Producer prod(*m_tractor->profile(), 0, fileName.toUtf8().constData());
+ if (prod.is_valid()) {
+ m_ruler->updatePreview(ix, true, true);
+ prod.set("mlt_service", "avformat-novalidate");
+ trackPlaylist.insert_at(ix, &prod, 1);
+ }
+ }
+ }
+ trackPlaylist.consolidate_blanks();
+ m_tractor->unlock();
+ if (timer)
+ m_previewTimer.start();
+}
diff --git a/src/timeline/timeline.h b/src/timeline/timeline.h
index fbf4432..31e4f53 100644
--- a/src/timeline/timeline.h
+++ b/src/timeline/timeline.h
@@ -209,6 +209,8 @@ private:
int m_verticalZoom;
QString m_documentErrors;
QList <QAction *> m_trackActions;
+ /** @brief sometimes grouped commands quickly send invalidate commands, so wait a little bit before processing*/
+ QTimer m_previewGatherTimer;
QTimer m_previewTimer;
void adjustTrackHeaders();
@@ -251,6 +253,8 @@ private slots:
void slotEnableZone(bool enable);
void gotPreviewRender(int frame, const QString &file, int progress);
void invalidatePreview(int startFrame, int endFrame);
+ void slotReloadChunks(QList <int> chunks);
+ void slotProcessDirtyChunks();
signals:
void mousePosition(int);