Commit 97b0ca55 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Mixes: add button in composition list widget to display only transitions....

Mixes: add button in composition list widget to display only transitions. Dragging a transition over a clip cut between 2 clips will add a same track mix
Related to #796
parent 177250f5
<!DOCTYPE kpartgui>
<transition tag="mix" id="mix" type="hidden">
<transition tag="mix" id="mix" type="audio">
<name>Audio Mix</name>
</transition>
......@@ -83,6 +83,9 @@ QVariantMap AssetListWidget::getMimeData(const QString &assetId) const
{
QVariantMap mimeData;
mimeData.insert(getMimeType(assetId), assetId);
if (isAudio(assetId)) {
mimeData.insert(QStringLiteral("type"), QStringLiteral("audio"));
}
return mimeData;
}
......
......@@ -50,6 +50,7 @@ public:
/** @brief Return mime type used for drag and drop. It can be kdenlive/effect,
kdenlive/composition or kdenlive/transition*/
virtual QString getMimeType(const QString &assetId) const = 0;
virtual bool isAudio(const QString &assetId) const = 0;
QVariantMap getMimeData(const QString &assetId) const;
......
......@@ -55,6 +55,17 @@ Rectangle {
assetlist.setFilterType("")
}
}
ToolButton {
id: showTransitions
visible: !isEffectList
iconName: "transform-move-horizontal"
checkable:true
exclusiveGroup: filterGroup
tooltip: i18n("Show transitions only")
onClicked: {
assetlist.setFilterType("transition")
}
}
ToolButton {
id: showVideo
visible: isEffectList
......
......@@ -638,7 +638,7 @@ int Core::getItemDuration(const ObjectId &id)
}
break;
default:
qWarning() << "unhandled object type";
qWarning() << "unhandled object type: "<<(int)id.first;
}
return 0;
}
......@@ -657,9 +657,10 @@ QSize Core::getItemFrameSize(const ObjectId &id)
case ObjectType::TimelineTrack:
case ObjectType::Master:
case ObjectType::TimelineComposition:
case ObjectType::TimelineMix:
return pCore->getCurrentFrameSize();
default:
qWarning() << "unhandled object type";
qWarning() << "unhandled object type frame size";
}
return pCore->getCurrentFrameSize();
}
......
......@@ -67,6 +67,11 @@ void EffectListWidget::setFilterType(const QString &type)
}
}
bool EffectListWidget::isAudio(const QString &assetId) const
{
return EffectsRepository::get()->isAudioEffect(assetId);
}
QString EffectListWidget::getMimeType(const QString &assetId) const
{
Q_UNUSED(assetId);
......
......@@ -26,7 +26,7 @@ public:
EffectListWidget(QWidget *parent = Q_NULLPTR);
~EffectListWidget() override;
void setFilterType(const QString &type);
bool isAudio(const QString &assetId) const override;
/** @brief Return mime type used for drag and drop. It will be kdenlive/effect*/
QString getMimeType(const QString &assetId) const override;
void updateFavorite(const QModelIndex &index);
......
......@@ -440,8 +440,8 @@ void MainWindow::init(const QString &mltPath)
connect(m_assetPanel, &AssetPanel::reloadEffect, m_effectList2, &EffectListWidget::reloadCustomEffect);
m_effectListDock = addDock(i18n("Effects"), QStringLiteral("effect_list"), m_effectList2);
m_transitionList2 = new TransitionListWidget(this);
m_transitionListDock = addDock(i18n("Compositions"), QStringLiteral("transition_list"), m_transitionList2);
m_compositionList = new TransitionListWidget(this);
m_compositionListDock = addDock(i18n("Compositions"), QStringLiteral("transition_list"), m_compositionList);
// Add monitors here to keep them at the right of the window
m_clipMonitorDock = addDock(i18n("Clip Monitor"), QStringLiteral("clip_monitor"), m_clipMonitor);
......@@ -487,7 +487,7 @@ void MainWindow::init(const QString &mltPath)
/// Tabify Widgets
tabifyDockWidget(m_clipMonitorDock, m_projectMonitorDock);
tabifyDockWidget(m_transitionListDock, m_effectListDock);
tabifyDockWidget(m_compositionListDock, m_effectListDock);
tabifyDockWidget(m_effectStackDock, pCore->bin()->clipPropertiesDock());
bool firstRun = readOptions();
......@@ -850,9 +850,9 @@ void MainWindow::slotThemeChanged(const QString &name)
// Trigger a repaint to have icons adapted
m_effectList2->reset();
}
if (m_transitionList2) {
if (m_compositionList) {
// Trigger a repaint to have icons adapted
m_transitionList2->reset();
m_compositionList->reset();
}
if (m_clipMonitor) {
m_clipMonitor->setPalette(plt);
......@@ -916,7 +916,7 @@ MainWindow::~MainWindow()
delete m_clipMonitor;
delete m_shortcutRemoveFocus;
delete m_effectList2;
delete m_transitionList2;
delete m_compositionList;
qDeleteAll(m_transitions);
// Mlt::Factory::close();
}
......@@ -2444,7 +2444,7 @@ void MainWindow::connectDocument()
m_normalEditTool->setChecked(true);
connect(m_projectMonitor, &Monitor::durationChanged, this, &MainWindow::slotUpdateProjectDuration);
connect(m_effectList2, &EffectListWidget::reloadFavorites, getMainTimeline(), &TimelineWidget::updateEffectFavorites);
connect(m_transitionList2, &TransitionListWidget::reloadFavorites, getMainTimeline(), &TimelineWidget::updateTransitionFavorites);
connect(m_compositionList, &TransitionListWidget::reloadFavorites, getMainTimeline(), &TimelineWidget::updateTransitionFavorites);
connect(pCore->bin(), &Bin::processDragEnd, getMainTimeline(), &TimelineWidget::endDrag);
// Load master effect zones
......
......@@ -182,8 +182,8 @@ private:
QDockWidget *m_projectBinDock;
QDockWidget *m_effectListDock;
QDockWidget *m_transitionListDock;
TransitionListWidget *m_transitionList2;
QDockWidget *m_compositionListDock;
TransitionListWidget *m_compositionList;
EffectListWidget *m_effectList2;
AssetPanel *m_assetPanel{nullptr};
......
......@@ -843,7 +843,7 @@ bool TimelineModel::requestClipMove(int clipId, int trackId, int position, bool
return true;
}
bool TimelineModel::mixClip(int idToMove, int delta)
bool TimelineModel::mixClip(int idToMove, const QString &mixId, int delta)
{
int selectedTrack = -1;
......@@ -980,7 +980,7 @@ bool TimelineModel::mixClip(int idToMove, int delta)
mixDurations.second = mixDuration - mixDurations.first;
}
}
bool result = requestClipMix(clipsToMix, mixDurations, selectedTrack, mixPosition, true, true, true, undo,
bool result = requestClipMix(mixId, clipsToMix, mixDurations, selectedTrack, mixPosition, true, true, true, undo,
redo, false);
if (result) {
// Check if this is an AV split group
......@@ -1004,8 +1004,8 @@ bool TimelineModel::mixClip(int idToMove, int delta)
clipsToMix.first = splitId;
clipsToMix.second = current_id;
}
if (splitId > -1 && clipsToMix.first != clipsToMix.second) {
result = requestClipMix(clipsToMix, mixDurations, splitTrack, mixPosition, true, true, true, undo, redo, false);
if (splitId > -1 && !getTrackById_const(splitTrack)->hasStartMix(clipsToMix.second) && clipsToMix.first != clipsToMix.second) {
result = requestClipMix(mixId, clipsToMix, mixDurations, splitTrack, mixPosition, true, true, true, undo, redo, false);
}
}
}
......@@ -1026,7 +1026,7 @@ bool TimelineModel::mixClip(int idToMove, int delta)
}
}
bool TimelineModel::requestClipMix(std::pair<int, int> clipIds, std::pair<int, int> mixDurations, int trackId, int position, bool updateView, bool invalidateTimeline, bool finalMove, Fun &undo, Fun &redo, bool groupMove)
bool TimelineModel::requestClipMix(const QString &mixId, std::pair<int, int> clipIds, std::pair<int, int> mixDurations, int trackId, int position, bool updateView, bool invalidateTimeline, bool finalMove, Fun &undo, Fun &redo, bool groupMove)
{
if (trackId == -1) {
return false;
......@@ -1053,7 +1053,7 @@ bool TimelineModel::requestClipMix(std::pair<int, int> clipIds, std::pair<int, i
if (notifyViewOnly) {
PUSH_LAMBDA(update_model, local_undo);
}
ok = getTrackById(trackId)->requestClipMix(clipIds, mixDurations, updateView, finalMove, local_undo, local_redo, groupMove);
ok = getTrackById(trackId)->requestClipMix(mixId, clipIds, mixDurations, updateView, finalMove, local_undo, local_redo, groupMove);
if (!ok) {
qWarning() << "mix failed, reverting";
bool undone = local_undo();
......@@ -5557,7 +5557,13 @@ int TimelineModel::getMixDuration(int cid) const
Q_ASSERT(isClip(cid));
int tid = m_allClips.at(cid)->getCurrentTrackId();
if (tid > -1) {
return getTrackById_const(tid)->getMixDuration(cid);
if (getTrackById_const(tid)->hasStartMix(cid)) {
return getTrackById_const(tid)->getMixDuration(cid);
} else {
// Mix is not yet inserted in timeline
std::pair<int, int> mixInOut = getMixInOut(cid);
return mixInOut.second - mixInOut.first;
}
}
return 0;
}
......
......@@ -360,7 +360,7 @@ public:
Q_INVOKABLE bool requestSubtitleMove(int clipId, int position, bool updateView = true, bool logUndo = true, bool invalidateTimeline = false);
bool requestSubtitleMove(int clipId, int position, bool updateView, bool first, bool last, bool invalidateTimeline, Fun &undo, Fun &redo);
bool cutSubtitle(int position, Fun &undo, Fun &redo);
bool requestClipMix(std::pair<int, int> clipIds, std::pair<int, int> mixDurations, int trackId, int position, bool updateView, bool invalidateTimeline, bool finalMove, Fun &undo, Fun &redo, bool groupMove);
bool requestClipMix(const QString &mixId, std::pair<int, int> clipIds, std::pair<int, int> mixDurations, int trackId, int position, bool updateView, bool invalidateTimeline, bool finalMove, Fun &undo, Fun &redo, bool groupMove);
/** @brief Move a composition to a specific position This action is undoable
Returns true on success. If it fails, nothing is modified. If the clip is
......@@ -747,7 +747,7 @@ public:
/** @brief Import project's master effects */
void importMasterEffects(std::weak_ptr<Mlt::Service> service);
/** @brief Create a mix selection with currently selected clip. If delta = -1, mix with previous clip, +1 with next clip and 0 will check cursor position*/
bool mixClip(int idToMove = -1, int delta = 0);
bool mixClip(int idToMove = -1, const QString &mixId = QStringLiteral("luma"), int delta = 0);
Q_INVOKABLE bool resizeStartMix(int cid, int duration, bool singleResize);
void requestResizeMix(int cid, int duration, MixAlignment align, int leftFrames = -1);
/** @brief Get Mix cut pos (the duration of the mix on the right clip) */
......
......@@ -1711,7 +1711,7 @@ bool TrackModel::requestRemoveMix(std::pair<int, int> clipIds, Fun &undo, Fun &r
return false;
}
bool TrackModel::requestClipMix(std::pair<int, int> clipIds, std::pair<int, int> mixDurations, bool updateView, bool finalMove, Fun &undo, Fun &redo, bool groupMove)
bool TrackModel::requestClipMix(const QString &mixId, std::pair<int, int> clipIds, std::pair<int, int> mixDurations, bool updateView, bool finalMove, Fun &undo, Fun &redo, bool groupMove)
{
QWriteLocker locker(&m_lock);
// By default, insertion occurs in topmost track
......@@ -1906,33 +1906,36 @@ bool TrackModel::requestClipMix(std::pair<int, int> clipIds, std::pair<int, int>
};
}
// Create mix compositing
Fun build_mix = [clipIds, mixPosition, mixDurations, dest_track, secondClipCut, this]() {
Fun build_mix = [clipIds, mixPosition, mixDurations, dest_track, secondClipCut, mixId, this]() {
if (auto ptr = m_parent.lock()) {
std::shared_ptr<ClipModel> movedClip(ptr->getClipPtr(clipIds.second));
movedClip->setMixDuration(mixDurations.first + mixDurations.second, secondClipCut);
// Insert mix transition
QString assetName;
std::unique_ptr<Mlt::Transition>t;
QDomElement xml;
if (isAudioTrack()) {
t = std::make_unique<Mlt::Transition>(*ptr->getProfile(), "mix");
// Mix is the only audio transition
t = TransitionsRepository::get()->getTransition(QStringLiteral("mix"));
t->set_in_and_out(mixPosition, mixPosition + mixDurations.first + mixDurations.second);
t->set("kdenlive:mixcut", secondClipCut);
t->set("start", -1);
t->set("accepts_blanks", 1);
m_track->plant_transition(*t.get(), 0, 1);
assetName = QStringLiteral("mix");
xml = TransitionsRepository::get()->getXml(assetName);
} else {
t = std::make_unique<Mlt::Transition>(*ptr->getProfile(), "luma");
assetName = mixId.isEmpty() || mixId == QLatin1String("mix") ? QStringLiteral("luma") : mixId;
t = TransitionsRepository::get()->getTransition(assetName);
t->set_in_and_out(mixPosition, mixPosition + mixDurations.first + mixDurations.second);
xml = TransitionsRepository::get()->getXml(assetName);
t->set("kdenlive:mixcut", secondClipCut);
t->set("kdenlive_id", "luma");
m_track->plant_transition(*t.get(), 0, 1);
if (dest_track == 0) {
t->set("reverse", 1);
}
assetName = QStringLiteral("luma");
}
QDomElement xml = TransitionsRepository::get()->getXml(assetName);
if (dest_track == 0 && Xml::hasXmlParameter(xml, QStringLiteral("reverse"))) {
Xml::setXmlParameter(xml, QStringLiteral("reverse"), QStringLiteral("1"));
}
......@@ -2343,6 +2346,32 @@ bool TrackModel::hasStartMix(int cid) const
return m_sameCompositions.count(cid) > 0;
}
int TrackModel::isOnCut(int cid)
{
if (auto ptr = m_parent.lock()) {
std::shared_ptr<CompositionModel> composition = ptr->getCompositionPtr(cid);
int startPos = composition->getPosition();
int endPos = startPos + composition->getPlaytime() - 1;
int cid1 = getClipByPosition(startPos);
int cid2 = getClipByPosition(endPos);
if (cid1 == -1 || cid2 == -1 || cid1 == cid2) {
return -1;
}
if (m_mixList.contains(cid1) || m_sameCompositions.count(cid2) > 0) {
// Clips are already mixed, abort
return -1;
}
std::shared_ptr<ClipModel> clip = ptr->getClipPtr(cid2);
int mixRight = clip->getPosition();
std::shared_ptr<ClipModel> clip2 = ptr->getClipPtr(cid1);
int mixLeft = clip2->getPosition() + clip2->getPlaytime();
if (mixLeft == mixRight) {
return mixLeft;
}
}
return -1;
}
bool TrackModel::hasEndMix(int cid) const
{
return m_mixList.contains(cid);
......
......@@ -110,7 +110,7 @@ public:
/** @brief Remove a composition between 2 same track clips */
bool requestRemoveMix(std::pair<int, int> clipIds, Fun &undo, Fun &redo);
/** @brief Create a composition between 2 same track clips */
bool requestClipMix(std::pair<int, int> clipIds, std::pair<int, int> mixDurations, bool updateView, bool finalMove, Fun &undo, Fun &redo, bool groupMove);
bool requestClipMix(const QString &mixId, std::pair<int, int> clipIds, std::pair<int, int> mixDurations, bool updateView, bool finalMove, Fun &undo, Fun &redo, bool groupMove);
/** @brief Get clip ids and in/out position for mixes in this clip */
std::pair<MixInfo, MixInfo> getMixInfo(int cid) const;
/** @brief Delete a mix composition */
......@@ -320,6 +320,9 @@ protected:
bool hasStartMix(int cid) const;
/** @brief Returns true if this clip has a mix at end */
bool hasEndMix(int cid) const;
/** @brief Returns the cut position if the composition is over a cut between 2 clips, -1 otherwise
*/
int isOnCut(int cid);
/** @brief Returns all mix info as xml */
QDomElement mixXml(QDomDocument &document, int cid) const;
......
......@@ -270,6 +270,7 @@ Rectangle {
clipDropArea.lastDragUuid = ""
scrollTimer.running = false
scrollTimer.stop()
sameTrackIndicator.visible = false
}
function isDragging() {
......@@ -494,17 +495,21 @@ Rectangle {
}
DropArea { //Drop area for compositions
id: compoArea
width: root.width - headerWidth
height: root.height - ruler.height
y: ruler.height
x: headerWidth
property bool isAudioDrag
property int sameCutPos: -1
keys: 'kdenlive/composition'
onEntered: {
if (clipBeingMovedId == -1 && clipBeingDroppedId == -1) {
var track = Logic.getTrackIdFromPos(drag.y + scrollView.contentY - subtitleTrack.height)
var frame = Math.round((drag.x + scrollView.contentX) / timeline.scaleFactor)
droppedPosition = frame
if (track >= 0 && !controller.isAudioTrack(track)) {
isAudioDrag = drag.getDataAsString('type') == "audio"
if (track >= 0 && controller.isAudioTrack(track) == isAudioDrag) {
clipBeingDroppedData = drag.getDataAsString('kdenlive/composition')
clipBeingDroppedId = timeline.insertComposition(track, frame, clipBeingDroppedData, false)
continuousScrolling(drag.x + scrollView.contentX, drag.y + scrollView.contentY)
......@@ -520,13 +525,30 @@ Rectangle {
if (track !== -1) {
var frame = Math.round((drag.x + scrollView.contentX) / timeline.scaleFactor)
if (clipBeingDroppedId >= 0) {
if (controller.isAudioTrack(track)) {
if (controller.isAudioTrack(track) != isAudioDrag) {
// Don't allow moving composition to an audio track
track = controller.getCompositionTrackId(clipBeingDroppedId)
}
controller.suggestCompositionMove(clipBeingDroppedId, track, frame, root.consumerPosition, root.snapping)
var moveData = controller.suggestCompositionMove(clipBeingDroppedId, track, frame, root.consumerPosition, root.snapping)
var currentFrame = moveData[0]
var currentTrack = moveData[1]
sameCutPos = timeline.isOnCut(clipBeingDroppedId)
if (sameCutPos > -1) {
var sourceTrack = Logic.getTrackById(currentTrack)
if (drag.y < sourceTrack.y + sourceTrack.height / 2 || isAudioDrag) {
sameTrackIndicator.x = sameCutPos * timeline.scaleFactor - scrollView.contentX - sameTrackIndicator.width / 2
sameTrackIndicator.y = sourceTrack.y
sameTrackIndicator.height = sourceTrack.height
sameTrackIndicator.visible = true
} else {
sameTrackIndicator.visible = false
}
} else {
sameTrackIndicator.visible = false
}
continuousScrolling(drag.x + scrollView.contentX, drag.y + scrollView.contentY)
} else if (!controller.isAudioTrack(track)) {
} else if (controller.isAudioTrack(track) == isAudioDrag) {
frame = controller.suggestSnapPoint(frame, root.snapping)
clipBeingDroppedData = drag.getDataAsString('kdenlive/composition')
clipBeingDroppedId = timeline.insertComposition(track, frame, clipBeingDroppedData , false)
......@@ -548,7 +570,14 @@ Rectangle {
var track = controller.getCompositionTrackId(clipBeingDroppedId)
// we simulate insertion at the final position so that stored undo has correct value
controller.requestItemDeletion(clipBeingDroppedId, false)
timeline.insertNewComposition(track, frame, clipBeingDroppedData, true)
if (sameTrackIndicator.visible) {
// We want a same track composition
timeline.insertNewMix(track, sameCutPos, clipBeingDroppedData)
} else if (!isAudioDrag) {
timeline.insertNewComposition(track, frame, clipBeingDroppedData, true)
} else {
// Cannot insert an audio mix composition
}
}
clearDropData()
}
......@@ -1778,6 +1807,14 @@ Rectangle {
z: 100
}
}
Rectangle {
id: sameTrackIndicator
color: 'red'
opacity: 0.5
visible: false
width: root.baseUnit
height: width
}
}
Repeater { id: guidesRepeater;
model: guidesDelegateModel
......
......@@ -386,6 +386,14 @@ QList<int> TimelineController::insertClips(int tid, int position, const QStringL
return clipIds;
}
void TimelineController::insertNewMix(int tid, int position, const QString transitionId)
{
int clipId = m_model->getTrackById_const(tid)->getClipByPosition(position);
if (clipId > 0) {
m_model->mixClip(clipId, transitionId);
}
}
int TimelineController::insertNewComposition(int tid, int position, const QString &transitionId, bool logUndo)
{
int clipId = m_model->getTrackById_const(tid)->getClipByPosition(position);
......@@ -476,6 +484,13 @@ int TimelineController::insertNewComposition(int tid, int clipId, int offset, co
return id;
}
int TimelineController::isOnCut(int cid) const
{
Q_ASSERT(m_model->isComposition(cid));
int tid = m_model->getItemTrackId(cid);
return m_model->getTrackById_const(tid)->isOnCut(cid);
}
int TimelineController::insertComposition(int tid, int position, const QString &transitionId, bool logUndo)
{
int id;
......@@ -4408,7 +4423,7 @@ void TimelineController::addTracks(int videoTracks, int audioTracks)
void TimelineController::mixClip(int cid, int delta)
{
m_model->mixClip(cid, delta);
m_model->mixClip(cid, QStringLiteral("luma"), delta);
}
void TimelineController::temporaryUnplug(QList<int> clipIds, bool hide)
......
......@@ -221,6 +221,15 @@ public:
@return the id of the inserted composition
*/
Q_INVOKABLE int insertComposition(int tid, int position, const QString &transitionId, bool logUndo);
/** @brief Request inserting a new mix in timeline (dragged from compositions list)
@param tid is the destination track
@param position is the timeline position
@param transitionId is the data describing the dropped composition
*/
Q_INVOKABLE void insertNewMix(int tid, int position, const QString transitionId);
/** @brief Returns the cut position if the composition is over a cut between 2 clips, -1 otherwise
*/
Q_INVOKABLE int isOnCut(int cid) const;
/** @brief Request inserting a new composition in timeline (dragged from compositions list)
this function will check if there is a clip at insert point and
adjust the composition length accordingly
......
......@@ -39,6 +39,9 @@ bool TransitionFilter::filterType(const std::shared_ptr<TreeItem> &item) const
if (m_type_value == AssetListType::AssetType::Favorites) {
return item->dataColumn(AssetTreeModel::favCol).toBool();
}
if (m_type_value == AssetListType::AssetType::VideoTransition) {
return itemType == m_type_value || itemType == AssetListType::AssetType::AudioTransition;
}
return itemType == m_type_value;
}
......
......@@ -35,11 +35,10 @@ std::shared_ptr<TransitionTreeModel> TransitionTreeModel::construct(bool flat, Q
for (const auto &transition : qAsConst(allTransitions)) {
std::shared_ptr<TreeItem> targetCategory = compoCategory;
AssetListType::AssetType type = TransitionsRepository::get()->getType(transition.first);
if (type == AssetListType::AssetType::AudioTransition || type == AssetListType::AssetType::VideoTransition) {
targetCategory = transCategory;
}
if (flat) {
targetCategory = self->rootItem;
} else if (type == AssetListType::AssetType::AudioTransition || type == AssetListType::AssetType::VideoTransition) {
targetCategory = transCategory;
}
// we create the data list corresponding to this transition
......
......@@ -19,7 +19,6 @@
TransitionListWidget::TransitionListWidget(QWidget *parent)
: AssetListWidget(parent)
{
m_model = TransitionTreeModel::construct(true, this);
m_proxyModel = std::make_unique<TransitionFilter>(this);
......@@ -40,12 +39,17 @@ TransitionListWidget::~TransitionListWidget()
{
}
bool TransitionListWidget::isAudio(const QString &assetId) const
{
return TransitionsRepository::get()->isAudio(assetId);
}
QString TransitionListWidget::getMimeType(const QString &assetId) const
{
if (TransitionsRepository::get()->isComposition(assetId)) {
/*if (TransitionsRepository::get()->isComposition(assetId)) {
return QStringLiteral("kdenlive/composition");
}
return QStringLiteral("kdenlive/transition");
}*/
return QStringLiteral("kdenlive/composition");
}
void TransitionListWidget::updateFavorite(const QModelIndex &index)
......@@ -59,6 +63,8 @@ void TransitionListWidget::setFilterType(const QString &type)
{
if (type == "favorites") {
static_cast<TransitionFilter *>(m_proxyModel.get())->setFilterType(true, AssetListType::AssetType::Favorites);
} else if (type == "transition") {
static_cast<TransitionFilter *>(m_proxyModel.get())->setFilterType(true, AssetListType::AssetType::VideoTransition);
} else {
static_cast<TransitionFilter *>(m_proxyModel.get())->setFilterType(false, AssetListType::AssetType::Favorites);
}
......
......@@ -22,6 +22,7 @@ public:
TransitionListWidget(QWidget *parent = Q_NULLPTR);
~TransitionListWidget() override;
void setFilterType(const QString &type);
bool isAudio(const QString &assetId) const override;
/** @brief Return mime type used for drag and drop. It will be kdenlive/composition
or kdenlive/transition*/
QString getMimeType(const QString &assetId) const override;
......
Supports Markdown
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