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

Spacer tool should not allow moving items before another clip

parent 2c87162c
......@@ -71,6 +71,7 @@ QStringList waitingBinIds;
QMap<QString, QString> mappedIds;
QMap<int, int> tracksMap;
QMap<int, int> spacerUngroupedItems;
int spacerMinPosition;
QSemaphore semaphore(1);
bool TimelineFunctions::cloneClip(const std::shared_ptr<TimelineItemModel> &timeline, int clipId, int &newId, PlaylistState::ClipState state, Fun &undo,
......@@ -327,6 +328,7 @@ int TimelineFunctions::requestSpacerStartOperation(const std::shared_ptr<Timelin
{
std::unordered_set<int> clips = timeline->getItemsInRange(trackId, position, -1);
timeline->requestClearSelection();
spacerMinPosition = -1;
if (!clips.empty()) {
// Remove grouped items that are before the click position
// First get top groups ids
......@@ -386,6 +388,30 @@ int TimelineFunctions::requestSpacerStartOperation(const std::shared_ptr<Timelin
timeline->m_groups->ungroupItem(i.key(), undo, redo);
}
timeline->requestSetSelection(roots);
if (firstPosition > 0) {
// Find minimum position, parse all tracks
if (trackId > -1) {
// Easy, check blank size
int spaceDuration = timeline->getTrackById_const(trackId)->getBlankSizeAtPos(firstPosition - 1);
if (spaceDuration > 0 ) {
spacerMinPosition = firstPosition - spaceDuration;
}
} else {
// Check space in all tracks
auto it = timeline->m_allTracks.cbegin();
int space = -1;
while (it != timeline->m_allTracks.cend()) {
int spaceDuration = timeline->getTrackById_const((*it)->getId())->getBlankSizeAtPos(firstPosition - 1);
if (space == -1 || spaceDuration < space) {
space = spaceDuration;
}
++it;
}
if (space > -1) {
spacerMinPosition = firstPosition - space;
}
}
}
return (firstCid);
}
return -1;
......@@ -394,6 +420,7 @@ int TimelineFunctions::requestSpacerStartOperation(const std::shared_ptr<Timelin
bool TimelineFunctions::requestSpacerEndOperation(const std::shared_ptr<TimelineItemModel> &timeline, int itemId, int startPosition, int endPosition, int affectedTrack, bool moveGuides, Fun &undo, Fun &redo)
{
// Move group back to original position
spacerMinPosition = -1;
int track = timeline->getItemTrackId(itemId);
bool isClip = timeline->isClip(itemId);
if (isClip) {
......@@ -1905,6 +1932,9 @@ bool TimelineFunctions::requestDeleteBlankAt(const std::shared_ptr<TimelineItemM
} else {
spaceDuration = timeline->getTrackById_const(trackId)->getBlankSizeAtPos(position);
}
if (spaceDuration <= 0) {
return false;
}
int cid = requestSpacerStartOperation(timeline, affectAllTracks ? -1 : trackId, position);
if (cid == -1) {
return false;
......@@ -2133,3 +2163,7 @@ QDomDocument TimelineFunctions::extractClip(const std::shared_ptr<TimelineItemMo
return destDoc;
}
int TimelineFunctions::spacerMinPos()
{
return spacerMinPosition;
}
......@@ -135,6 +135,8 @@ struct TimelineFunctions
/** @brief This function extracts the content of an xml playlist file and converts it to json paste format
*/
static QDomDocument extractClip(const std::shared_ptr<TimelineItemModel> &timeline, int cid, const QString &binId);
static int spacerMinPos();
};
#endif
......@@ -457,14 +457,22 @@ int TrackModel::getBlankSizeAtPos(int frame)
{
READ_LOCK();
int min_length = 0;
int blank_length = 0;
for (auto &m_playlist : m_playlists) {
int ix = m_playlist.get_clip_index_at(frame);
if (m_playlist.is_blank(ix)) {
int blank_length = m_playlist.clip_length(ix);
if (min_length == 0 || (blank_length > 0 && blank_length < min_length)) {
min_length = blank_length;
if (frame >= m_playlist.get_length()) {
blank_length = frame - m_playlist.get_length() + 1;
} else {
int ix = m_playlist.get_clip_index_at(frame);
if (m_playlist.is_blank(ix)) {
blank_length = m_playlist.clip_length(ix);
} else {
// There is a clip at that position, abort
return 0;
}
}
if (min_length == 0 || blank_length < min_length) {
min_length = blank_length;
}
}
return min_length;
}
......
......@@ -409,6 +409,7 @@ Rectangle {
property bool subtitlesDisabled: timeline.subtitlesDisabled
property int trackTagWidth: fontMetrics.boundingRect("M").width * ((getAudioTracksCount() > 9) || (trackHeaderRepeater.count - getAudioTracksCount() > 9) ? 3 : 2)
property bool scrollVertically: timeline.scrollVertically
property int spacerMinPos: 0
onSeekingFinishedChanged : {
playhead.opacity = seekingFinished ? 1 : 0.5
......@@ -1155,6 +1156,7 @@ Rectangle {
}
spacerGroup = timeline.requestSpacerStartOperation(spacerTrack, frame)
spacerMinPos = timeline.spacerMinPos()
if (spacerGroup > -1 || spacerGuides) {
drag.axis = Drag.XAxis
Drag.active = true
......@@ -1256,6 +1258,7 @@ Rectangle {
// Spacer tool, move group
var track = controller.getItemTrackId(spacerGroup)
var frame = Math.round((mouse.x + scrollView.contentX) / timeline.scaleFactor) + spacerFrame - spacerClickFrame
frame = Math.max(spacerMinPos, frame)
finalSpacerFrame = controller.suggestItemMove(spacerGroup, track, frame, root.consumerPosition, (mouse.modifiers & Qt.ShiftModifier) ? 0 : root.snapping)[0]
continuousScrolling(mouse.x + scrollView.contentX, mouse.y + scrollView.contentY)
} else if (spacerGuides) {
......
......@@ -1625,7 +1625,6 @@ void TimelineController::cutAllClipsUnderCursor(int position)
position = pCore->getTimelinePosition();
}
QMutexLocker lk(&m_metaMutex);
TimelineFunctions::requestClipCutAll(m_model, position);
}
......@@ -1636,6 +1635,11 @@ int TimelineController::requestSpacerStartOperation(int trackId, int position)
return itemId;
}
int TimelineController::spacerMinPos() const
{
return TimelineFunctions::spacerMinPos();
}
bool TimelineController::requestSpacerEndOperation(int clipId, int startPosition, int endPosition, int affectedTrack, int guideStart)
{
QMutexLocker lk(&m_metaMutex);
......
......@@ -396,6 +396,9 @@ public:
/** @brief Request a spacer operation
*/
Q_INVOKABLE int requestSpacerStartOperation(int trackId, int position);
/** @brief Returns the minimum available position for a spacer operation
*/
Q_INVOKABLE int spacerMinPos() const;
/** @brief Request a spacer operation
*/
Q_INVOKABLE bool requestSpacerEndOperation(int clipId, int startPosition, int endPosition, int affectedTrack, int guideStart = -1);
......
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