Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Reintroduce effect compare and timeline preview (wip)

parent 16a5fc92
......@@ -28,23 +28,37 @@
#include "model/assetparametermodel.hpp"
#include "transitions/transitionsrepository.hpp"
#include "view/assetparameterview.hpp"
#include "utils/KoIconUtils.h"
#include "definitions.h"
#include <KColorScheme>
#include <KColorUtils>
#include <KSqueezedTextLabel>
#include <QApplication>
#include <QDebug>
#include <QLabel>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QToolButton>
#include <klocalizedstring.h>
AssetPanel::AssetPanel(QWidget *parent)
: QScrollArea(parent)
, m_lay(new QVBoxLayout(this))
, m_assetTitle(new QLabel(this))
, m_assetTitle(new KSqueezedTextLabel(this))
, m_transitionWidget(new TransitionStackView(this))
, m_effectStackWidget(new EffectStackView(this))
{
m_lay->addWidget(m_assetTitle);
QHBoxLayout *tLayout = new QHBoxLayout;
tLayout->addWidget(m_assetTitle);
m_splitButton = new QToolButton(this);
m_splitButton->setIcon(KoIconUtils::themedIcon(QStringLiteral("view-split-left-right")));
m_splitButton->setToolTip(i18n("Compare effect"));
m_splitButton->setCheckable(true);
m_splitButton->setVisible(false);
connect(m_splitButton, &QToolButton::toggled, this, &AssetPanel::processSplitEffect);
tLayout->addWidget(m_splitButton);
m_lay->addLayout(tLayout);
m_lay->addWidget(m_transitionWidget);
m_lay->addWidget(m_effectStackWidget);
m_transitionWidget->setVisible(false);
......@@ -70,6 +84,7 @@ void AssetPanel::showEffectStack(const QString &clipName, std::shared_ptr<Effect
return;
}
m_assetTitle->setText(i18n("%1 effects", clipName));
m_splitButton->setVisible(true);
m_effectStackWidget->setVisible(true);
m_effectStackWidget->setModel(effectsModel, range);
}
......@@ -94,6 +109,7 @@ void AssetPanel::clear()
m_transitionWidget->setProperty("compositionId", QVariant());
m_transitionWidget->unsetModel();
m_effectStackWidget->setVisible(false);
m_splitButton->setVisible(false);
m_effectStackWidget->setProperty("clipId", QVariant());
m_effectStackWidget->unsetModel();
m_assetTitle->setText(QString());
......@@ -170,3 +186,13 @@ const QString AssetPanel::getStyleSheet()
return stylesheet;
}
void AssetPanel::processSplitEffect(bool enable)
{
ObjectType id = m_effectStackWidget->stackOwner();
if (id == ObjectType::TimelineClip) {
emit doSplitEffect(enable);
} else if (id == ObjectType::BinClip) {
emit doSplitBinEffect(enable);
}
}
......@@ -26,6 +26,9 @@
#include <QVBoxLayout>
#include <memory>
class KSqueezedTextLabel;
class QToolButton;
/** @brief This class is the widget that provides interaction with the asset currently selected.
That is, it either displays an effectStack or the parameters of a transition
*/
......@@ -64,11 +67,20 @@ public slots:
protected:
/** @brief Return the stylesheet used to display the panel (based on current palette). */
static const QString getStyleSheet();
QVBoxLayout *m_lay;
QLabel *m_assetTitle;
KSqueezedTextLabel *m_assetTitle;
TransitionStackView *m_transitionWidget;
EffectStackView *m_effectStackWidget;
private:
QToolButton *m_splitButton;
private slots:
void processSplitEffect(bool enable);
signals:
void doSplitEffect(bool);
void doSplitBinEffect(bool);
};
#endif
......@@ -39,7 +39,7 @@ enum MonitorId { NoMonitor = 0x01, ClipMonitor = 0x02, ProjectMonitor = 0x04, Re
const int DefaultThumbHeight = 100;
}
enum class ObjectType { TimelineClip, TimelineComposition, TimelineTrack, BinClip };
enum class ObjectType { TimelineClip, TimelineComposition, TimelineTrack, BinClip, NoItem };
using ObjectId = std::pair<ObjectType, int>;
enum OperationType {
......
......@@ -69,6 +69,7 @@ EffectStackView::EffectStackView(QWidget *parent)
: QWidget(parent)
, m_thumbnailer(new AssetIconProvider(true))
, m_range(-1, -1)
, m_model(nullptr)
{
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
m_lay = new QVBoxLayout(this);
......@@ -258,3 +259,11 @@ void EffectStackView::setRange(int in, int out)
static_cast<CollapsibleEffectView *>(w)->setRange(m_range);
}
}
ObjectType EffectStackView::stackOwner() const
{
if (m_model) {
return m_model->getOwnerId().first;
}
return ObjectType::NoItem;
}
......@@ -26,6 +26,7 @@
#include <QWidget>
#include <QMutex>
#include <memory>
#include "definitions.h"
class QVBoxLayout;
class QTreeView;
......@@ -58,6 +59,7 @@ public:
void setModel(std::shared_ptr<EffectStackModel> model, QPair<int, int> range);
void unsetModel(bool reset = true);
void setRange(int in, int out);
ObjectType stackOwner() const;
protected:
void dragEnterEvent(QDragEnterEvent *event) override;
......
......@@ -1356,13 +1356,13 @@ void EffectStackView2::slotSwitchCompare(bool enable)
} else {
pos = m_effectMetaInfo.monitor->position();
}
m_effectMetaInfo.monitor->slotSwitchCompare(enable, pos);
m_effectMetaInfo.monitor->slotSwitchCompare(enable);
} else {
if (m_status == TIMELINE_CLIP) {
pos = m_effectMetaInfo.monitor->position() + m_clipref->startPos().frames(KdenliveSettings::project_fps());
} else {
pos = m_effectMetaInfo.monitor->position();
}
m_effectMetaInfo.monitor->slotSwitchCompare(enable, pos);
m_effectMetaInfo.monitor->slotSwitchCompare(enable);
}
}
......@@ -310,6 +310,8 @@ void MainWindow::init()
m_assetPanel = new AssetPanel(this);
connect(m_assetPanel, &AssetPanel::doSplitEffect, m_projectMonitor, &Monitor::slotSwitchCompare);
connect(m_assetPanel, &AssetPanel::doSplitBinEffect, m_clipMonitor, &Monitor::slotSwitchCompare);
connect(m_timelineTabs, &TimelineTabs::showTransitionModel, m_assetPanel, &AssetPanel::showTransition);
connect(m_timelineTabs, &TimelineTabs::showClipEffectStack, m_assetPanel, &AssetPanel::showEffectStack);
connect(pCore->bin(), &Bin::requestShowEffectStack, m_assetPanel, &AssetPanel::showEffectStack);
......@@ -881,20 +883,13 @@ void MainWindow::slotConnectMonitors()
void MainWindow::createSplitOverlay(Mlt::Filter *filter)
{
//TODO
if (pCore->projectManager()->currentTimeline()) {
if (pCore->projectManager()->currentTimeline()->projectView()->createSplitOverlay(filter)) {
m_projectMonitor->activateSplit();
}
}
getMainTimeline()->controller()->createSplitOverlay(filter);
m_projectMonitor->activateSplit();
}
void MainWindow::removeSplitOverlay()
{
//TODO
if (pCore->projectManager()->currentTimeline()) {
pCore->projectManager()->currentTimeline()->projectView()->removeSplitOverlay();
}
getMainTimeline()->controller()->removeSplitOverlay();
}
void MainWindow::addAction(const QString &name, QAction *action)
......@@ -2515,35 +2510,35 @@ void MainWindow::slotLiftZone()
void MainWindow::slotPreviewRender()
{
if (pCore->currentDoc()) {
pCore->projectManager()->currentTimeline()->startPreviewRender();
getCurrentTimeline()->controller()->startPreviewRender();
}
}
void MainWindow::slotStopPreviewRender()
{
if (pCore->currentDoc()) {
pCore->projectManager()->currentTimeline()->stopPreviewRender();
getCurrentTimeline()->controller()->stopPreviewRender();
}
}
void MainWindow::slotDefinePreviewRender()
{
if (pCore->currentDoc()) {
pCore->projectManager()->currentTimeline()->addPreviewRange(true);
getCurrentTimeline()->controller()->addPreviewRange(true);
}
}
void MainWindow::slotRemovePreviewRender()
{
if (pCore->currentDoc()) {
pCore->projectManager()->currentTimeline()->addPreviewRange(false);
getCurrentTimeline()->controller()->addPreviewRange(false);
}
}
void MainWindow::slotClearPreviewRender()
{
if (pCore->currentDoc()) {
pCore->projectManager()->currentTimeline()->clearPreviewRange();
getCurrentTimeline()->controller()->clearPreviewRange();
}
}
......
......@@ -716,15 +716,7 @@ void ClipController::updateEffect(const ProfileInfo &pInfo, const QDomElement &e
bool ClipController::hasEffects() const
{
Mlt::Service service = m_masterProducer->parent();
for (int ix = 0; ix < service.filter_count(); ++ix) {
QScopedPointer<Mlt::Filter> effect(service.filter(ix));
QString id = effect->get("kdenlive_ix");
if (!id.isEmpty()) {
return true;
}
}
return false;
return m_effectStack->rowCount() > 0;
}
void ClipController::setBinEffectsEnabled(bool enabled)
......
......@@ -1349,11 +1349,11 @@ void GLWidget::updateGamma()
reconfigure();
}
const QString GLWidget::sceneList(const QString &root)
const QString GLWidget::sceneList(const QString &root, const QString &fullPath)
{
QString playlist;
qCDebug(KDENLIVE_LOG) << " * * *Setting document xml root: " << root;
Mlt::Consumer xmlConsumer(*m_monitorProfile, "xml:kdenlive_playlist");
Mlt::Consumer xmlConsumer(*m_monitorProfile, fullPath.isEmpty() ? "xml:kdenlive_playlist" : fullPath.toUtf8().constData());
if (!root.isEmpty()) {
xmlConsumer.set("root", root.toUtf8().constData());
}
......@@ -1372,7 +1372,7 @@ const QString GLWidget::sceneList(const QString &root)
}
xmlConsumer.connect(prod);
xmlConsumer.run();
playlist = QString::fromUtf8(xmlConsumer.get("kdenlive_playlist"));
playlist = fullPath.isEmpty() ? QString::fromUtf8(xmlConsumer.get("kdenlive_playlist")) : fullPath;
return playlist;
}
......
......@@ -75,7 +75,7 @@ public:
int reconfigure(Mlt::Profile *profile = nullptr);
/** @brief Get the current MLT producer playlist.
* @return A string describing the playlist */
const QString sceneList(const QString &root);
const QString sceneList(const QString &root, const QString &fullPath = QString());
int displayWidth() const { return m_rect.width(); }
void updateAudioForAnalysis();
......
......@@ -1331,7 +1331,7 @@ void Monitor::slotOpenClip(std::shared_ptr<ProjectClip> controller, int in, int
if (m_playAction->isActive()) {
m_playAction->setActive(false);
}
m_glMonitor->setProducer(m_controller->masterProducer(), isActive(), in);
m_glMonitor->setProducer(m_controller->originalProducer().get(), isActive(), in);
m_audioMeterWidget->audioChannels = controller->audioInfo() ? controller->audioInfo()->channels() : 0;
emit requestAudioThumb(controller->AbstractProjectItem::clipId());
// hasEffects = controller->hasEffects();
......@@ -1399,9 +1399,9 @@ void Monitor::resetProfile()
render->saveSceneList(path, info);
}*/
const QString Monitor::sceneList(const QString &root)
const QString Monitor::sceneList(const QString &root, const QString &fullPath)
{
return m_glMonitor->sceneList(root);
return m_glMonitor->sceneList(root, fullPath);
}
void Monitor::updateClipZone()
......@@ -1719,7 +1719,7 @@ void Monitor::activateSplit()
slotActivateMonitor(true);
}
void Monitor::slotSwitchCompare(bool enable, int pos)
void Monitor::slotSwitchCompare(bool enable)
{
if (m_id == Kdenlive::ProjectMonitor) {
if (enable) {
......@@ -1752,9 +1752,9 @@ void Monitor::slotSwitchCompare(bool enable, int pos)
if (m_controller == nullptr || !m_controller->hasEffects()) {
// disable split effect
if (m_controller) {
// warningMessage(i18n("Clip has no effects"));
pCore->displayMessage(i18n("Clip has no effects"), InformationMessage);
} else {
// warningMessage(i18n("Select a clip in project bin to compare effect"));
pCore->displayMessage(i18n("Select a clip in project bin to compare effect"), InformationMessage);
}
return;
}
......@@ -1763,10 +1763,10 @@ void Monitor::slotSwitchCompare(bool enable, int pos)
// Split scene is already active
return;
}
buildSplitEffect(m_controller->masterProducer(), pos);
buildSplitEffect(m_controller->masterProducer());
} else if (m_splitEffect) {
//TODO
//render->setProducer(m_controller->masterProducer(), pos, isActive());
m_glMonitor->setProducer(m_controller->originalProducer().get(), isActive(), position());
delete m_splitEffect;
m_splitProducer = nullptr;
m_splitEffect = nullptr;
......@@ -1775,9 +1775,9 @@ void Monitor::slotSwitchCompare(bool enable, int pos)
slotActivateMonitor();
}
void Monitor::buildSplitEffect(Mlt::Producer *original, int pos)
void Monitor::buildSplitEffect(Mlt::Producer *original)
{
//TODO
qDebug()<<"// BUILDING SPLIT EFFECT!!!";
m_splitEffect = new Mlt::Filter(*profile(), "frei0r.alphagrad");
if ((m_splitEffect != nullptr) && m_splitEffect->is_valid()) {
m_splitEffect->set("0", 0.5); // 0 is the Clip left parameter
......@@ -1785,17 +1785,18 @@ void Monitor::buildSplitEffect(Mlt::Producer *original, int pos)
m_splitEffect->set("2", -0.747); // 2 is tilt
} else {
// frei0r.scal0tilt is not available
warningMessage(i18n("The alphagrad filter is required for that feature, please install frei0r and restart Kdenlive"));
pCore->displayMessage(i18n("The alphagrad filter is required for that feature, please install frei0r and restart Kdenlive"), ErrorMessage);
return;
}
QString splitTransition = TransitionHandler::compositeTransition();
QString splitTransition = TimelineItemModel::getCompositingTransition();
Mlt::Transition t(*profile(), splitTransition.toUtf8().constData());
if (!t.is_valid()) {
delete m_splitEffect;
warningMessage(i18n("The cairoblend transition is required for that feature, please install frei0r and restart Kdenlive"));
pCore->displayMessage(i18n("The cairoblend transition is required for that feature, please install frei0r and restart Kdenlive"), ErrorMessage);
return;
}
Mlt::Tractor trac(*profile());
//TODO: remove usage of Clip class
Clip clp(*original);
Mlt::Producer *clone = clp.clone();
Clip clp2(*clone);
......@@ -1808,7 +1809,7 @@ void Monitor::buildSplitEffect(Mlt::Producer *original, int pos)
delete clone;
delete original;
m_splitProducer = new Mlt::Producer(trac.get_producer());
//render->setProducer(m_splitProducer, pos, isActive());
m_glMonitor->setProducer(m_splitProducer, isActive(), position());
loadQmlScene(MonitorSceneSplit);
}
......@@ -1929,7 +1930,7 @@ void Monitor::slotAdjustEffectCompare()
if (m_splitEffect) {
m_splitEffect->set("0", percent);
}
//render->doRefresh();
m_glMonitor->refresh();
}
ProfileInfo Monitor::profileInfo() const
......
......@@ -95,7 +95,7 @@ public:
void resetProfile();
void setCustomProfile(const QString &profile, const Timecode &tc);
void setupMenu(QMenu *goMenu, QMenu *overlayMenu, QAction *playZone, QAction *loopZone, QMenu *markerMenu = nullptr, QAction *loopClip = nullptr);
const QString sceneList(const QString &root);
const QString sceneList(const QString &root, const QString &fullPath = QString());
const QString activeClipId();
int position();
void updateTimecodeFormat();
......@@ -238,7 +238,7 @@ private:
/** @brief Check and display dropped frames */
void checkDrops(int dropped);
/** @brief Create temporary Mlt::Tractor holding a clip and it's effectless clone */
void buildSplitEffect(Mlt::Producer *original, int pos);
void buildSplitEffect(Mlt::Producer *original);
private slots:
Q_DECL_DEPRECATED void seekCursor(int pos);
......@@ -301,7 +301,6 @@ public slots:
void slotRewind(double speed = 0);
void slotRewindOneFrame(int diff = 1);
void slotForwardOneFrame(int diff = 1);
// void saveSceneList(const QString &path, const QDomElement &info = QDomElement());
void slotStart();
void slotEnd();
void slotSetZoneStart();
......@@ -318,7 +317,7 @@ public slots:
void slotShowEffectScene(MonitorSceneType sceneType, bool temporary = false);
bool effectSceneDisplayed(MonitorSceneType effectType);
/** @brief split screen to compare clip with and without effect */
void slotSwitchCompare(bool enable, int pos);
void slotSwitchCompare(bool enable);
void slotMouseSeek(int eventDelta, int modifiers) override;
void slotSwitchFullScreen(bool minimizeOnly = false) override;
/** @brief Display or hide the record toolbar */
......
......@@ -127,7 +127,7 @@ void Clip::deleteEffects()
int ct = 0;
Mlt::Filter *filter = m_producer.filter(ct);
while (filter != nullptr) {
QString ix = QString::fromLatin1(filter->get("kdenlive_ix"));
QString ix = QString::fromLatin1(filter->get("kdenlive_id"));
if (!ix.isEmpty()) {
if (m_producer.detach(*filter) == 0) {
} else {
......
This diff is collapsed.
......@@ -27,8 +27,7 @@
#include <QMutex>
#include <QTimer>
class KdenliveDoc;
class CustomRuler;
class TimelineController;
namespace Mlt {
class Tractor;
......@@ -50,16 +49,18 @@ class PreviewManager : public QObject
Q_OBJECT
public:
explicit PreviewManager(KdenliveDoc *doc, CustomRuler *ruler, Mlt::Tractor *tractor);
friend class TimelineController;
explicit PreviewManager(TimelineController *controller, Mlt::Tractor *tractor);
virtual ~PreviewManager();
/** @brief: initialize base variables, return false if error. */
bool initialize();
/** @brief: a timeline operation caused changes to frames between startFrame and endFrame. */
void invalidatePreview(int startFrame, int endFrame);
/** @brief: after a small delay (some operations trigger several invalidatePreview calls), take care of these invalidated chunks. */
void invalidatePreviews(const QList<int> &chunks);
void invalidatePreviews(const QVariantList &chunks);
/** @brief: user adds current timeline zone to the preview zone. */
void addPreviewRange(bool add);
void addPreviewRange(const QPoint zone, bool add);
/** @brief: Remove all existing previews. */
void clearPreviewRange();
/** @brief: stops current rendering process. */
......@@ -77,13 +78,19 @@ public:
/** @brief: Returns directory currently used to store the preview files. */
const QDir getCacheDir() const;
/** @brief: Load existing ruler chunks. */
void loadChunks(const QStringList &previewChunks, QStringList dirtyChunks, const QDateTime &documentDate);
void loadChunks(QVariantList previewChunks, QVariantList dirtyChunks, const QDateTime &documentDate);
int setOverlayTrack(Mlt::Playlist *overlay);
/** @brief Remove the effect compare overlay track */
void removeOverlayTrack();
/** @brief The current preview chunk being processed, -1 if none */
int workingPreview;
private:
KdenliveDoc *m_doc;
CustomRuler *m_ruler;
TimelineController *m_controller;
Mlt::Tractor *m_tractor;
Mlt::Playlist *m_previewTrack;
Mlt::Playlist *m_overlayTrack;
int m_previewTrackIndex;
/** @brief: The directory used to store the preview files. */
QDir m_cacheDir;
/** @brief: The directory used to store undo history of preview files (child of m_cacheDir). */
......@@ -100,7 +107,7 @@ private:
QList<int> m_waitingThumbs;
QFuture<void> m_previewThread;
/** @brief: After an undo/redo, if we have preview history, use it. */
void reloadChunks(const QList<int> &chunks);
void reloadChunks(const QVariantList chunks);
private slots:
/** @brief: To avoid filling the hard drive, remove preview undo history after 5 steps. */
......@@ -118,6 +125,10 @@ public slots:
/** @brief: A chunk has been created, notify ruler. */
void gotPreviewRender(int frame, const QString &file, int progress);
protected:
QVariantList m_renderedChunks;
QVariantList m_dirtyChunks;
signals:
void abortPreview();
void cleanupOldPreviews();
......
......@@ -2003,8 +2003,17 @@ void Timeline::loadPreviewRender()
return;
}
m_timelinePreview->buildPreviewTrack();
m_timelinePreview->loadChunks(chunks.split(QLatin1Char(','), QString::SkipEmptyParts), dirty.split(QLatin1Char(','), QString::SkipEmptyParts),
documentDate);
QList <int> renderedChunks;
QList <int> dirtyChunks;
QStringList chunksList = chunks.split(QLatin1Char(','), QString::SkipEmptyParts);
QStringList dirtyList = dirty.split(QLatin1Char(','), QString::SkipEmptyParts);
for (const QString &frame : chunksList) {
renderedChunks << frame.toInt();
}
for (const QString &frame : dirtyList) {
dirtyChunks << frame.toInt();
}
//m_timelinePreview->loadChunks(renderedChunks, dirtyChunks, documentDate);
m_usePreview = true;
} else {
m_ruler->hidePreview(true);
......@@ -2054,7 +2063,7 @@ void Timeline::initializePreview()
m_timelinePreview = nullptr;
}
} else {
m_timelinePreview = new PreviewManager(m_doc, m_ruler, m_tractor);
m_timelinePreview = nullptr; //new PreviewManager(m_tractor);
if (!m_timelinePreview->initialize()) {
// TODO warn user
m_ruler->hidePreview(true);
......@@ -2107,7 +2116,7 @@ void Timeline::disablePreview(bool disable)
m_tractor->unlock();
}
QPair<QStringList, QStringList> chunks = m_ruler->previewChunks();
m_timelinePreview->loadChunks(chunks.first, chunks.second, QDateTime());
//m_timelinePreview->loadChunks(chunks.first, chunks.second, QDateTime());
m_ruler->hidePreview(false);
m_usePreview = true;
}
......@@ -2117,7 +2126,7 @@ void Timeline::disablePreview(bool disable)
void Timeline::addPreviewRange(bool add)
{
if (m_timelinePreview) {
m_timelinePreview->addPreviewRange(add);
m_timelinePreview->addPreviewRange(QPoint(), add);
}
}
......
......@@ -96,6 +96,7 @@ public:
friend class TrackModel;
friend class TimelineModel;
friend class TimelineItemModel;
friend class TimelineController;
protected:
Mlt::Producer *service() const override;
......
......@@ -59,6 +59,7 @@ TimelineModel::TimelineModel(Mlt::Profile *profile, std::weak_ptr<DocUndoStack>
, m_timelineEffectsEnabled(true)
, m_id(getNextId())
, m_temporarySelectionGroup(-1)
, m_overlayTrackIndex(-1)
{
// Create black background track
m_blackClip->set("id", "black_track");
......@@ -94,6 +95,9 @@ int TimelineModel::getTracksCount() const
{
READ_LOCK();
int count = m_tractor->count();
if (m_overlayTrackIndex > -1) {
count --;
}
Q_ASSERT(count >= 0);
// don't count the black background track
Q_ASSERT(count - 1 == static_cast<int>(m_allTracks.size()));
......@@ -874,6 +878,7 @@ bool TimelineModel::requestTrackInsertion(int position, int &id)
bool TimelineModel::requestTrackInsertion(int position, int &id, Fun &undo, Fun &redo)
{
// TODO: make sure we disable overlayTrack before inserting a track
if (position == -1) {
position = (int)(m_allTracks.size());
}
......@@ -897,6 +902,7 @@ bool TimelineModel::requestTrackInsertion(int position, int &id, Fun &undo, Fun
bool TimelineModel::requestTrackDeletion(int trackId)
{
// TODO: make sure we disable overlayTrack before deleting a track
#ifdef LOGGING
m_logFile << "timeline->requestTrackDeletion(" << trackId << "); " << std::endl;
#endif
......@@ -1668,3 +1674,4 @@ void TimelineModel::requestClipReload(int clipId)
getTrackById(old_trackId)->requestClipInsertion(clipId, oldPos, false, local_undo, local_redo);
}
}
......@@ -481,6 +481,7 @@ public:
/** @brief Returns the effectstack of a given clip. */
std::shared_ptr<EffectStackModel> getClipEffectStack(int itemId);
protected:
/* @brief Register a new track. This is a call-back meant to be called from TrackModel
@param pos indicates the number of the track we are adding. If this is -1, then we add at the end.
......@@ -592,6 +593,9 @@ protected:
// id of the currently selected group in timeline, should be destroyed on each new selection
int m_temporarySelectionGroup;
// The index of the temporary overlay track in tractor, or -1 if not connected
int m_overlayTrackIndex;
// what follows are some virtual function that corresponds to the QML. They are implemented in TimelineItemModel
protected:
virtual void _beginRemoveRows(const QModelIndex &, int, int) = 0;
......
......@@ -833,4 +833,3 @@ bool TrackModel::hasIntersectingComposition(int in, int out) const
return false;
}
......@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.0
import QtQuick 2.6
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
......@@ -28,6 +28,7 @@ Rectangle {
property real timeScale: timeline.scaleFactor
property real fontUnit: root.baseUnit * 0.9
property alias rulerZone : zone
property int workingPreview : timeline.workingPreview
SystemPalette { id: activePalette }
......@@ -46,11 +47,62 @@ Rectangle {
adjustStepSize()
}
/*onDirtyChunksChanged: {
console.log('new chunks RES: ' , dirtyChunks)
//for (var i = 0; i < dirtyChunks.count; i++)
// console.log('new chunks: ' , dirtyChunks[i])
}*/
id: rulerTop
enabled: false
height: fontMetrics.font.pixelSize * 2
color: activePalette.window
Repeater {
model: timeline.dirtyChunks
anchors.fill: rulerTop
delegate: Rectangle {
x: scrollView.flickableItem.contentX / stepSize + modelData * rulerTop.timeScale
y: 0
width: 25 * rulerTop.timeScale
height: rulerTop.height / 4
color: 'darkred'
}
}
Repeater {
model: timeline.renderedChunks