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

Commit 3569ac05 authored by Nicolas Carion's avatar Nicolas Carion

nicer split track computed on drop

parent b671f7ed
......@@ -3663,7 +3663,7 @@ void MainWindow::slotInsertZoneToTimeline()
{
QPoint info = m_clipMonitor->getZoneInfo();
QString clipData = QString("%1#%2#%3").arg(m_clipMonitor->activeClipId()).arg(info.x()).arg(info.y());
int cid = getMainTimeline()->controller()->insertClip(-1, -1, clipData, true, true);
int cid = getMainTimeline()->controller()->insertClip(-1, -1, clipData, true, true, true);
if (cid == -1) {
pCore->displayMessage(i18n("Cannot insert clip at requested position"), InformationMessage);
} else {
......
......@@ -68,7 +68,7 @@ bool TimelineFunctions::requestMultipleClipsInsertion(std::shared_ptr<TimelineIt
for (const QString &binId : binIds) {
int clipId;
if (timeline->requestClipInsertion(binId, trackId, position, clipId, logUndo, refreshView, undo, redo)) {
if (timeline->requestClipInsertion(binId, trackId, position, clipId, logUndo, refreshView, true, undo, redo)) {
clipIds.append(clipId);
position += timeline->getItemPlaytime(clipId);
} else {
......@@ -250,7 +250,7 @@ bool TimelineFunctions::insertZone(std::shared_ptr<TimelineItemModel> timeline,
}
int newId = -1;
QString binClipId = QString("%1/%2/%3").arg(binId).arg(zone.x()).arg(zone.y() - 1);
timeline->requestClipInsertion(binClipId, trackId, insertFrame, newId, true, true, undo, redo);
timeline->requestClipInsertion(binClipId, trackId, insertFrame, newId, true, true, true, undo, redo);
pCore->pushUndo(undo, redo, overwrite ? i18n("Overwrite zone") : i18n("Insert zone"));
return result;
}
......
......@@ -267,10 +267,10 @@ QList<int> TimelineModel::getLowerTracksId(int trackId, TrackType type) const
results << (*it)->getId();
continue;
}
int audioTrack = (*it)->getProperty("kdenlive:audio_track").toInt();
if (type == TrackType::AudioTrack && audioTrack == 1) {
bool audioTrack = (*it)->isAudioTrack();
if (type == TrackType::AudioTrack && audioTrack) {
results << (*it)->getId();
} else if (type == TrackType::VideoTrack && audioTrack == 0) {
} else if (type == TrackType::VideoTrack && !audioTrack) {
results << (*it)->getId();
}
}
......@@ -284,13 +284,38 @@ int TimelineModel::getPreviousVideoTrackPos(int trackId) const
auto it = m_iteratorTable.at(trackId);
while (it != m_allTracks.begin()) {
--it;
if (it != m_allTracks.begin() && (*it)->getProperty("kdenlive:audio_track").toInt() == 0) {
if (it != m_allTracks.begin() && !(*it)->isAudioTrack()) {
break;
}
}
return it == m_allTracks.begin() ? 0 : getTrackMltIndex((*it)->getId());
}
int TimelineModel::getMirrorAudioTrackId(int trackId) const
{
READ_LOCK();
Q_ASSERT(isTrack(trackId));
auto it = m_iteratorTable.at(trackId);
if ((*it)->isAudioTrack()) {
// we expected a video track...
return -1;
}
int count = 0;
--it;
while (it != m_allTracks.begin()) {
if (!(*it)->isAudioTrack()) {
count++;
} else {
if (count == 0) {
return (*it)->getId();
}
count--;
}
--it;
}
return -1;
}
bool TimelineModel::requestClipMove(int clipId, int trackId, int position, bool updateView, bool invalidateTimeline, Fun &undo, Fun &redo)
{
qDebug() << "// FINAL MOVE: " << invalidateTimeline << ", UPDATE VIEW: " << updateView;
......@@ -538,21 +563,6 @@ int TimelineModel::suggestCompositionMove(int compoId, int trackId, int position
return position;
}
bool TimelineModel::requestClipInsertion(const QString &binClipId, int trackId, int position, int &id, bool logUndo, bool refreshView)
{
#ifdef LOGGING
m_logFile << "timeline->requestClipInsertion(" << binClipId.toStdString() << "," << trackId << " ," << position << ", dummy_id );" << std::endl;
#endif
QWriteLocker locker(&m_lock);
Fun undo = []() { return true; };
Fun redo = []() { return true; };
bool result = requestClipInsertion(binClipId, trackId, position, id, logUndo, refreshView, undo, redo);
if (result && logUndo) {
PUSH_UNDO(undo, redo, i18n("Insert Clip"));
}
return result;
}
bool TimelineModel::requestClipCreation(const QString &binClipId, int &id, PlaylistState::ClipState state, Fun &undo, Fun &redo)
{
qDebug() << "requestClipCreation " << binClipId;
......@@ -592,7 +602,23 @@ bool TimelineModel::requestClipCreation(const QString &binClipId, int &id, Playl
return true;
}
bool TimelineModel::requestClipInsertion(const QString &binClipId, int trackId, int position, int &id, bool logUndo, bool refreshView, Fun &undo, Fun &redo)
bool TimelineModel::requestClipInsertion(const QString &binClipId, int trackId, int position, int &id, bool logUndo, bool refreshView, bool useTargets)
{
#ifdef LOGGING
m_logFile << "timeline->requestClipInsertion(" << binClipId.toStdString() << "," << trackId << " ," << position << ", dummy_id );" << std::endl;
#endif
QWriteLocker locker(&m_lock);
Fun undo = []() { return true; };
Fun redo = []() { return true; };
bool result = requestClipInsertion(binClipId, trackId, position, id, logUndo, refreshView, useTargets, undo, redo);
if (result && logUndo) {
PUSH_UNDO(undo, redo, i18n("Insert Clip"));
}
return result;
}
bool TimelineModel::requestClipInsertion(const QString &binClipId, int trackId, int position, int &id, bool logUndo, bool refreshView, bool useTargets,
Fun &undo, Fun &redo)
{
std::function<bool(void)> local_undo = []() { return true; };
std::function<bool(void)> local_redo = []() { return true; };
......@@ -611,7 +637,7 @@ bool TimelineModel::requestClipInsertion(const QString &binClipId, int trackId,
type = master->clipType();
if (type == ClipType::AV) {
if (m_audioTarget >= 0 && m_videoTarget == -1) {
if (m_audioTarget >= 0 && m_videoTarget == -1 && !useTargets) {
// If audio target is set but no video target, only insert audio
trackId = m_audioTarget;
}
......@@ -627,8 +653,17 @@ bool TimelineModel::requestClipInsertion(const QString &binClipId, int trackId,
audioDrop = true;
}
}
if (res && !audioDrop) {
QList<int> possibleTracks = m_audioTarget >= 0 ? QList<int>() << m_audioTarget : getLowerTracksId(trackId, TrackType::AudioTrack);
if (res && (!audioDrop || !useTargets)) {
int target_track = m_audioTarget;
if (!useTargets) {
target_track = getMirrorAudioTrackId(trackId);
}
// QList<int> possibleTracks = m_audioTarget >= 0 ? QList<int>() << m_audioTarget : getLowerTracksId(trackId, TrackType::AudioTrack);
QList<int> possibleTracks;
qDebug() << "CREATING SPLIT " << target_track << " usetargets" << useTargets;
if (target_track >= 0) {
possibleTracks << target_track;
}
if (possibleTracks.isEmpty()) {
// No available audio track for splitting, abort
pCore->displayMessage(i18n("No available audio track for split operation"), ErrorMessage);
......
......@@ -104,13 +104,13 @@ public:
/// Two level model: tracks and clips on track
enum {
NameRole = Qt::UserRole + 1,
ResourceRole, /// clip only
ServiceRole, /// clip only
IsBlankRole, /// clip only
StartRole, /// clip only
BinIdRole, /// clip only
MarkersRole, /// clip only
StatusRole, /// clip only
ResourceRole, /// clip only
ServiceRole, /// clip only
IsBlankRole, /// clip only
StartRole, /// clip only
BinIdRole, /// clip only
MarkersRole, /// clip only
StatusRole, /// clip only
GroupDragRole, /// indicates if the clip is in current timeline selection, needed for group drag
KeyframesRole,
DurationRole,
......@@ -128,13 +128,13 @@ public:
IsCompositeRole, /// track only
IsLockedRole, /// track only
HeightRole, /// track only
TrackTagRole, /// track only
TrackTagRole, /// track only
FadeInRole, /// clip only
FadeOutRole, /// clip only
IsCompositionRole, /// clip only
FileHashRole, /// clip only
SpeedRole, /// clip only
ReloadThumbRole, /// clip only
ReloadThumbRole, /// clip only
ItemATrack, /// composition only
ItemIdRole
};
......@@ -247,13 +247,16 @@ public:
Returns an empty list if no track available
@param trackId Id of the track to test
*/
QList <int> getLowerTracksId(int trackId, TrackType type = TrackType::AnyTrack) const;
QList<int> getLowerTracksId(int trackId, TrackType type = TrackType::AnyTrack) const;
/* @brief Returns the MLT track index of the video track just below the given trackC
@param trackId Id of the track to test
*/
int getPreviousVideoTrackPos(int trackId) const;
/* @brief Retuns the Id of the corresponding audio track. If trackId corresponds to video1, this will return audio 1 and so on */
int getMirrorAudioTrackId(int trackId) const;
/* @brief Move a clip to a specific position
This action is undoable
Returns true on success. If it fails, nothing is modified.
......@@ -307,10 +310,13 @@ public:
@param ID return parameter of the id of the inserted clip
@param logUndo if set to false, no undo object is stored
@param refreshView whether the view should be refreshed
@param useTargets: if true, the Audio/video split will occur on the set targets. Otherwise, they will be computed as an offset from the middle line
*/
bool requestClipInsertion(const QString &binClipId, int trackId, int position, int &id, bool logUndo = true, bool refreshView = false);
bool requestClipInsertion(const QString &binClipId, int trackId, int position, int &id, bool logUndo = true, bool refreshView = false,
bool useTargets = true);
/* Same function, but accumulates undo and redo*/
bool requestClipInsertion(const QString &binClipId, int trackId, int position, int &id, bool logUndo, bool refreshView, Fun &undo, Fun &redo);
bool requestClipInsertion(const QString &binClipId, int trackId, int position, int &id, bool logUndo, bool refreshView, bool useTargets, Fun &undo,
Fun &redo);
/* @brief Creates a new clip instance without inserting it.
This action is undoable, returns true on success
@param binClipId: Bin id of the clip to insert
......@@ -472,9 +478,11 @@ public:
@param id return parameter of the id of the inserted composition
@param logUndo if set to false, no undo object is stored
*/
bool requestCompositionInsertion(const QString &transitionId, int trackId, int position, int length, Mlt::Properties *transProps, int &id, bool logUndo = true);
bool requestCompositionInsertion(const QString &transitionId, int trackId, int position, int length, Mlt::Properties *transProps, int &id,
bool logUndo = true);
/* Same function, but accumulates undo and redo*/
bool requestCompositionInsertion(const QString &transitionId, int trackId, int compositionTrack, int position, int length, Mlt::Properties *transProps, int &id, Fun &undo, Fun &redo);
bool requestCompositionInsertion(const QString &transitionId, int trackId, int compositionTrack, int position, int length, Mlt::Properties *transProps,
int &id, Fun &undo, Fun &redo);
/* @brief This function change the global (timeline-wise) enabled state of the effects
It disables/enables track and clip effects (recursively)
......@@ -523,11 +531,11 @@ protected:
void registerTrack(std::shared_ptr<TrackModel> track, int pos = -1, bool doInsert = true, bool reloadView = true);
/* @brief Register a new clip. This is a call-back meant to be called from ClipModel
*/
*/
void registerClip(const std::shared_ptr<ClipModel> &clip);
/* @brief Register a new composition. This is a call-back meant to be called from CompositionModel
*/
*/
void registerComposition(const std::shared_ptr<CompositionModel> &composition);
/* @brief Register a new group. This is a call-back meant to be called from GroupsModel
......@@ -644,7 +652,7 @@ protected:
// The index of the temporary overlay track in tractor, or -1 if not connected
int m_overlayTrackCount;
// The preferred audio target for clip insertion or -1 if not defined
int m_audioTarget;
// The preferred video target for clip insertion or -1 if not defined
......
......@@ -219,9 +219,9 @@ Rectangle {
var id = -1
if (binIds.length == 1) {
id = timeline.insertClip(timeline.activeTrack, frame, clipBeingDroppedData, false, true)
id = timeline.insertClip(timeline.activeTrack, frame, clipBeingDroppedData, false, true, false)
} else {
var ids = timeline.insertClips(timeline.activeTrack, frame, binIds, false, true)
var ids = timeline.insertClips(timeline.activeTrack, frame, binIds, false, true, false)
// if the clip insertion succeeded, request the clips to be grouped
if (ids.length > 0) {
......@@ -290,7 +290,7 @@ Rectangle {
var binIds = clipBeingDroppedData.split(";")
if (binIds.length == 1) {
timeline.insertClip(track, frame, clipBeingDroppedData, true, true)
timeline.insertClip(track, frame, clipBeingDroppedData, true, true, false)
} else {
timeline.insertClips(track, frame, binIds, true, true)
}
......
......@@ -386,7 +386,7 @@ bool TimelineController::scrub()
return false;
}
int TimelineController::insertClip(int tid, int position, const QString &data_str, bool logUndo, bool refreshView)
int TimelineController::insertClip(int tid, int position, const QString &data_str, bool logUndo, bool refreshView, bool useTargets)
{
int id;
if (tid == -1) {
......@@ -395,7 +395,7 @@ int TimelineController::insertClip(int tid, int position, const QString &data_st
if (position == -1) {
position = timelinePosition();
}
if (!m_model->requestClipInsertion(data_str, tid, position, id, logUndo, refreshView)) {
if (!m_model->requestClipInsertion(data_str, tid, position, id, logUndo, refreshView, useTargets)) {
id = -1;
}
return id;
......
......@@ -120,7 +120,7 @@ public:
@param logUndo if set to false, no undo object is stored
@return the id of the inserted clip
*/
Q_INVOKABLE int insertClip(int tid, int position, const QString &xml, bool logUndo, bool refreshView);
Q_INVOKABLE int insertClip(int tid, int position, const QString &xml, bool logUndo, bool refreshView, bool useTargets);
/* @brief Request inserting multiple clips into the timeline (dragged from bin or monitor)
* @param tid is the destination track
* @param position is the timeline position
......
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