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

Expose mix duration and align buttons

parent 06181f0e
......@@ -1054,3 +1054,8 @@ void Core::testProxies()
QScopedPointer<ProxyTest> dialog(new ProxyTest(QApplication::activeWindow()));
dialog->exec();
}
void Core::resizeMix(int duration, MixAlignment align)
{
m_mainWindow->getCurrentTimeline()->controller()->resizeMix(duration, align);
}
......@@ -255,6 +255,8 @@ public:
TaskManager taskManager;
/** @brief The number of clip load jobs changed */
void loadingClips(int);
/** @brief Resize current mix item */
void resizeMix(int duration, MixAlignment align);
private:
explicit Core();
......
......@@ -53,6 +53,8 @@ GroupType groupTypeFromStr(const QString &s);
enum class ObjectType { TimelineClip, TimelineComposition, TimelineTrack, TimelineMix, TimelineSubtitle, BinClip, Master, NoItem };
using ObjectId = std::pair<ObjectType, int>;
enum class MixAlignment { AlignNone, AlignLeft, AlignRight, AlignCenter };
enum OperationType {
None = 0,
WaitingForConfirm,
......
......@@ -21,6 +21,7 @@
#include "core.h"
#include "doc/kthumb.h"
#include "timecodedisplay.h"
#include "kdenlivesettings.h"
#include "bin/projectclip.h"
#include "project/projectmanager.h"
......
......@@ -24,7 +24,6 @@
#include "definitions.h"
#include "timecode.h"
#include "timecodedisplay.h"
#include <QWidget>
#include <QTimer>
......@@ -32,6 +31,7 @@
#include "mlt++/Mlt.h"
class ProjectClip;
class TimecodeDisplay;
/**
......
......@@ -5315,6 +5315,79 @@ std::pair<int, int> TimelineModel::getMixInOut(int cid) const
return {-1,-1};
}
void TimelineModel::requestResizeMix(int cid, int duration, MixAlignment align)
{
Q_ASSERT(isClip(cid));
int tid = m_allClips.at(cid)->getCurrentTrackId();
if (tid > -1) {
MixInfo mixData = getTrackById_const(tid)->getMixInfo(cid).first;
int clipToResize = mixData.firstClipId;
if (clipToResize > -1) {
Fun undo = []() { return true; };
Fun redo = []() { return true; };
int cutPos = m_allClips.at(cid)->getPosition() + m_allClips.at(cid)->getMixDuration() - m_allClips.at(cid)->getMixCutPosition();
Fun adjust_mix_undo = [this, tid, cid, prevCut = m_allClips.at(cid)->getMixCutPosition(), prevDuration = m_allClips.at(cid)->getMixDuration()]() {
getTrackById_const(tid)->setMixDuration(cid, prevDuration, prevCut);
QModelIndex ix = makeClipIndexFromID(cid);
emit dataChanged(ix, ix, {TimelineModel::MixRole,TimelineModel::MixCutRole});
return true;
};
if (align == MixAlignment::AlignLeft) {
int updatedDuration = m_allClips.at(cid)->getPosition() + m_allClips.at(cid)->getPlaytime() - cutPos + duration;
int result = requestItemResize(cid, updatedDuration, false, true, undo, redo);
updatedDuration = cutPos - m_allClips.at(clipToResize)->getPosition();
result = requestItemResize(clipToResize, updatedDuration, true, true, undo, redo);
Fun adjust_mix = [this, tid, cid, duration]() {
getTrackById_const(tid)->setMixDuration(cid, duration, 0);
QModelIndex ix = makeClipIndexFromID(cid);
emit dataChanged(ix, ix, {TimelineModel::MixRole,TimelineModel::MixCutRole});
return true;
};
adjust_mix();
UPDATE_UNDO_REDO(adjust_mix, adjust_mix_undo, undo, redo);
} else if (align == MixAlignment::AlignRight) {
int updatedDuration = cutPos + duration - m_allClips.at(clipToResize)->getPosition();
int result = requestItemResize(clipToResize, updatedDuration, true, true, undo, redo);
updatedDuration = m_allClips.at(cid)->getPosition() + m_allClips.at(cid)->getPlaytime() - cutPos;
result = requestItemResize(cid, updatedDuration, false, true, undo, redo);
Fun adjust_mix = [this, tid, cid, duration]() {
getTrackById_const(tid)->setMixDuration(cid, duration, duration);
QModelIndex ix = makeClipIndexFromID(cid);
emit dataChanged(ix, ix, {TimelineModel::MixRole,TimelineModel::MixCutRole});
return true;
};
adjust_mix();
UPDATE_UNDO_REDO(adjust_mix, adjust_mix_undo, undo, redo);
} else if (align == MixAlignment::AlignCenter) {
int updatedDuration = m_allClips.at(cid)->getPosition() + m_allClips.at(cid)->getPlaytime() - cutPos + duration / 2;
int result = requestItemResize(cid, updatedDuration, false, true, undo, redo);
updatedDuration = cutPos + (duration - duration / 2) - m_allClips.at(clipToResize)->getPosition();
result = requestItemResize(clipToResize, updatedDuration, true, true, undo, redo);
Fun adjust_mix = [this, tid, cid, duration]() {
getTrackById_const(tid)->setMixDuration(cid, duration, (duration - duration / 2));
QModelIndex ix = makeClipIndexFromID(cid);
emit dataChanged(ix, ix, {TimelineModel::MixRole,TimelineModel::MixCutRole});
return true;
};
adjust_mix();
UPDATE_UNDO_REDO(adjust_mix, adjust_mix_undo, undo, redo);
} else {
Fun adjust_mix = [this, tid, cid, duration, updatedCut = m_allClips.at(cid)->getPosition() + duration - cutPos]() {
getTrackById_const(tid)->setMixDuration(cid, duration, updatedCut);
QModelIndex ix = makeClipIndexFromID(cid);
emit dataChanged(ix, ix, {TimelineModel::MixRole,TimelineModel::MixCutRole});
return true;
};
int updatedDuration = m_allClips.at(cid)->getPosition() + duration - m_allClips[clipToResize]->getPosition();
int result = requestItemResize(clipToResize, updatedDuration, true, true, undo, redo);
adjust_mix();
UPDATE_UNDO_REDO(adjust_mix, adjust_mix_undo, undo, redo);
}
pCore->pushUndo(undo, redo, i18n("Resize mix"));
}
}
}
void TimelineModel::setSubModel(std::shared_ptr<SubtitleModel> model)
{
m_subtitleModel = std::move(model);
......
......@@ -741,6 +741,7 @@ public:
/** @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);
Q_INVOKABLE bool resizeStartMix(int cid, int duration, bool singleResize);
void requestResizeMix(int cid, int duration, MixAlignment align);
std::shared_ptr<SubtitleModel> getSubtitleModel();
protected:
......
......@@ -2131,6 +2131,7 @@ void TrackModel::setMixDuration(int cid, int mixDuration, int mixCut)
{
m_allClips[cid]->setMixDuration(mixDuration, mixCut);
m_sameCompositions[cid]->getAsset()->set("kdenlive:mixcut", mixCut);
m_sameCompositions[cid]->dataChanged(QModelIndex(), QModelIndex(), {AssetParameterModel::ParentDurationRole});
}
void TrackModel::syncronizeMixes(bool finalMove)
......
......@@ -413,7 +413,7 @@ Rectangle {
onPressed: {
previousMix = clipRoot.mixDuration
root.autoScrolling = false
mixOut.color = 'darkorchid'
mixOut.color = 'red'
anchors.left = undefined
parent.anchors.right = undefined
mixCutPos.anchors.right = undefined
......@@ -449,7 +449,7 @@ Rectangle {
}
onEntered: {
if (!pressed) {
mixOut.color = 'darkorchid'
mixOut.color = 'red'
timeline.showToolTip(i18n("Mix:%1", timeline.simplifiedTC(clipRoot.mixDuration)))
}
}
......
......@@ -4368,3 +4368,10 @@ int TimelineController::clipMaxDuration(int cid)
}
return m_model->m_allClips[cid]->getMaxDuration();
}
void TimelineController::resizeMix(int duration, MixAlignment align)
{
if (m_model->m_selectedMix > -1) {
m_model->requestResizeMix(m_model->m_selectedMix, duration, align);
}
}
......@@ -665,6 +665,8 @@ public slots:
void saveTimelineSelection(const QDir &targetDir);
/** @brief Restore timeline scroll pos on open. */
void setScrollPos(int pos);
/** @brief Request resizing currently selected mix. */
void resizeMix(int duration, MixAlignment align);
/** @brief change zone info with undo. */
Q_INVOKABLE void updateZone(const QPoint oldZone, const QPoint newZone, bool withUndo = true);
Q_INVOKABLE void updateEffectZone(const QPoint oldZone, const QPoint newZone, bool withUndo = true);
......
......@@ -24,17 +24,42 @@
#include "assets/model/assetparametermodel.hpp"
#include "core.h"
#include "monitor/monitor.h"
#include "timecodedisplay.h"
#include <QComboBox>
#include <QSignalBlocker>
#include <QDebug>
#include <QHBoxLayout>
#include <QToolButton>
#include <QLabel>
#include <klocalizedstring.h>
MixStackView::MixStackView(QWidget *parent)
: AssetParameterView(parent)
{
m_durationLayout = new QHBoxLayout;
m_duration = new TimecodeDisplay(pCore->timecode(), this);
m_durationLayout->addWidget(new QLabel(i18n("Duration:")));
m_durationLayout->addWidget(m_duration);
m_alignLeft = new QToolButton(this);
m_alignLeft->setIcon(QIcon::fromTheme(QStringLiteral("align-horizontal-left")));
m_alignLeft->setToolTip(i18n("Align left"));
m_alignLeft->setAutoRaise(true);
connect(m_alignLeft, &QToolButton::clicked, this, &MixStackView::slotAlignLeft);
m_alignRight = new QToolButton(this);
m_alignRight->setIcon(QIcon::fromTheme(QStringLiteral("align-horizontal-right")));
m_alignRight->setToolTip(i18n("Align right"));
m_alignRight->setAutoRaise(true);
connect(m_alignRight, &QToolButton::clicked, this, &MixStackView::slotAlignRight);
m_alignCenter = new QToolButton(this);
m_alignCenter->setIcon(QIcon::fromTheme(QStringLiteral("align-horizontal-center")));
m_alignCenter->setToolTip(i18n("Center"));
m_alignCenter->setAutoRaise(true);
connect(m_alignCenter, &QToolButton::clicked, this, &MixStackView::slotAlignCenter);
m_durationLayout->addStretch();
m_durationLayout->addWidget(m_alignLeft);
m_durationLayout->addWidget(m_alignCenter);
m_durationLayout->addWidget(m_alignRight);
}
void MixStackView::setModel(const std::shared_ptr<AssetParameterModel> &model, QSize frameSize, bool addSpacer)
......@@ -52,18 +77,59 @@ void MixStackView::setModel(const std::shared_ptr<AssetParameterModel> &model, Q
});
emit initKeyframeView(true);
pCore->getMonitor(m_model->monitorId)->slotShowEffectScene(needsMonitorEffectScene());
if (m_model->rowCount() > 0) {
m_duration->setValue(m_model->data(m_model->index(0, 0), AssetParameterModel::ParentDurationRole).toInt());
connect(m_model.get(), &AssetParameterModel::dataChanged, this, &MixStackView::durationChanged);
}
connect(m_duration, &TimecodeDisplay::timeCodeUpdated, this, &MixStackView::updateDuration);
m_lay->addLayout(m_durationLayout);
m_lay->addStretch(10);
slotRefresh();
}
void MixStackView::durationChanged(const QModelIndex &, const QModelIndex &, const QVector<int> &roles)
{
if (roles.contains(AssetParameterModel::ParentDurationRole)) {
m_duration->setValue(m_model->data(m_model->index(0, 0), AssetParameterModel::ParentDurationRole).toInt());
}
}
void MixStackView::updateDuration()
{
int newDuration = m_duration->getValue();
pCore->resizeMix(newDuration, MixAlignment::AlignNone);
}
void MixStackView::slotAlignLeft()
{
int newDuration = m_duration->getValue();
pCore->resizeMix(newDuration, MixAlignment::AlignLeft);
}
void MixStackView::slotAlignRight()
{
int newDuration = m_duration->getValue();
pCore->resizeMix(newDuration, MixAlignment::AlignRight);
}
void MixStackView::slotAlignCenter()
{
int newDuration = m_duration->getValue();
pCore->resizeMix(newDuration, MixAlignment::AlignCenter);
}
void MixStackView::unsetModel()
{
if (m_model) {
m_model->setActive(false);
m_lay->removeItem(m_durationLayout);
auto kfr = m_model->getKeyframeModel();
if (kfr) {
disconnect(kfr.get(), &KeyframeModelList::modelChanged, this, &AssetParameterView::slotRefresh);
}
disconnect(m_model.get(), &AssetParameterModel::dataChanged, this, &MixStackView::durationChanged);
pCore->getMonitor(m_model->monitorId)->slotShowEffectScene(MonitorSceneDefault);
}
AssetParameterView::unsetModel();
......
......@@ -26,6 +26,9 @@
#include "definitions.h"
class QComboBox;
class QToolButton;
class TimecodeDisplay;
class QHBoxLayout;
class MixStackView : public AssetParameterView
{
......@@ -40,6 +43,20 @@ public:
signals:
void seekToTransPos(int pos);
private slots:
void durationChanged(const QModelIndex &, const QModelIndex &, const QVector<int> &roles);
void updateDuration();
void slotAlignLeft();
void slotAlignRight();
void slotAlignCenter();
private:
QHBoxLayout *m_durationLayout;
TimecodeDisplay *m_duration;
QToolButton *m_alignLeft;
QToolButton *m_alignCenter;
QToolButton *m_alignRight;
};
#endif
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