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

* Various fixes for clip move when dragging from bin, start implementing snapping

* Alt+arrow moves to previous/next snap point
parent 1d20a3c8
......@@ -2813,8 +2813,8 @@ void MainWindow::slotActivateTransitionView(Transition *transition)
void MainWindow::slotSnapRewind()
{
if (m_projectMonitor->isActive()) {
if (pCore->projectManager()->currentTimeline()) {
pCore->projectManager()->currentTimeline()->projectView()->slotSeekToPreviousSnap();
if (pCore->projectManager()->currentTimelineWidget()) {
pCore->projectManager()->currentTimelineWidget()->gotoPreviousSnap();
}
} else {
m_clipMonitor->slotSeekToPreviousSnap();
......@@ -2824,8 +2824,8 @@ void MainWindow::slotSnapRewind()
void MainWindow::slotSnapForward()
{
if (m_projectMonitor->isActive()) {
if (pCore->projectManager()->currentTimeline()) {
pCore->projectManager()->currentTimeline()->projectView()->slotSeekToNextSnap();
if (pCore->projectManager()->currentTimelineWidget()) {
pCore->projectManager()->currentTimelineWidget()->gotoNextSnap();
}
} else {
m_clipMonitor->slotSeekToNextSnap();
......
......@@ -66,6 +66,33 @@ int SnapModel::getClosestPoint(int position)
return (int)next;
}
int SnapModel::getNextPoint(int position)
{
if (m_snaps.size() == 0) {
return position;
}
auto it = m_snaps.lower_bound(position + 1);
long long int next = position;
if (it != m_snaps.end()) {
next = (*it).first;
}
return (int)next;
}
int SnapModel::getPreviousPoint(int position)
{
if (m_snaps.size() == 0) {
return 0;
}
auto it = m_snaps.lower_bound(position);
long long int prev = 0;
if (it != m_snaps.begin()) {
--it;
prev = (*it).first;
}
return (int)prev;
}
void SnapModel::ignore(const std::vector<int>& pts)
{
for (int pt : pts) {
......
......@@ -44,6 +44,12 @@ public:
/* @brief Retrieves closest point. Returns -1 if there is no snappoint available */
int getClosestPoint(int position);
/* @brief Retrieves next snap point. Returns position if there is no snappoint available */
int getNextPoint(int position);
/* @brief Retrieves previous snap point. Returns 0 if there is no snappoint available */
int getPreviousPoint(int position);
/* @brief Ignores the given positions until unIgnore() is called
You can make several call to this before unIgnoring
Note that you cannot remove ignored points.
......
......@@ -132,7 +132,7 @@ QModelIndex TimelineItemModel::parent(const QModelIndex &index) const
bool TimelineItemModel::availableSpace(int tid, int pos, int duration) const
{
return (getTrackById_const(tid)->getBlankEnd(pos) > pos + duration);
return (getTrackById_const(tid)->getBlankEnd(pos) >= pos + duration);
}
int TimelineItemModel::rowCount(const QModelIndex &parent) const
......
......@@ -753,3 +753,33 @@ void TimelineModel::setUndoStack(std::weak_ptr<DocUndoStack> undo_stack)
{
m_undoStack = undo_stack;
}
int TimelineModel::requestBestSnapPos(int pos, int length)
{
int snapped_start = m_snaps->getClosestPoint(pos);
int snapped_end = m_snaps->getClosestPoint(pos + length);
int startDiff = qAbs(pos - snapped_start);
int endDiff = qAbs(pos + length - snapped_end);
if (startDiff < endDiff && snapped_start >= 0) {
// snap to start
if (startDiff < 10) {
return snapped_start;
}
} else {
// snap to end
if (endDiff < 10 && snapped_end >= 0) {
return snapped_end - length;
}
}
return -1;
}
int TimelineModel::requestNextSnapPos(int pos)
{
return m_snaps->getNextPoint(pos);
}
int TimelineModel::requestPreviousSnapPos(int pos)
{
return m_snaps->getPreviousPoint(pos);
}
......@@ -256,6 +256,23 @@ public:
*/
void setUndoStack(std::weak_ptr<DocUndoStack> undo_stack);
/* @brief Requests the best snapped position for a clip
@param pos is the clip's requested position
@param length is the clip's duration
@returns best snap position or -1 if no snap point is near
*/
int requestBestSnapPos(int pos, int length);
/* @brief Requests the next snapped point
@param pos is the current position
*/
int requestNextSnapPos(int pos);
/* @brief Requests the previous snapped point
@param pos is the current position
*/
int requestPreviousSnapPos(int pos);
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.
......
......@@ -95,7 +95,7 @@ Fun TrackModel::requestClipInsertion_lambda(int cid, int position, bool updateVi
clip->setPosition(position);
clip->setCurrentTrackId(getId());
int new_in = clip->getPosition();
int new_out = new_in + clip->getPlaytime() - 1;
int new_out = new_in + clip->getPlaytime();
ptr->m_snaps->addPoint(new_in);
ptr->m_snaps->addPoint(new_out);
if (updateView) {
......@@ -185,7 +185,7 @@ Fun TrackModel::requestClipDeletion_lambda(int cid, bool updateView)
delete prod;
if (auto ptr = m_parent.lock()) {
ptr->m_snaps->removePoint(old_in);
ptr->m_snaps->removePoint(old_out);
ptr->m_snaps->removePoint(old_out + 1);
qDebug() << "update" <<updateView;
}
return true;
......
......@@ -41,8 +41,10 @@ function getTrackFromPos(pos) {
}
function dragging(pos, duration) {
console.log("clip duration:", duration)
console.log("clip drag pos:", pos.x)
if (tracksRepeater.count > 0) {
var oldPosX = dropTarget.x
var oldPosY = dropTarget.y
var headerHeight = ruler.height
dropTarget.x = pos.x + headerWidth
dropTarget.width = duration * timeline.scaleFactor
......@@ -66,7 +68,7 @@ function dragging(pos, duration) {
}
if (i === tracksRepeater.count || pos.x <= 0)
dropTarget.visible = false
console.log("clip drag pos2:", dropTarget.x)
// Scroll tracks if at edges.
if (pos.x > scrollView.width - 50) {
// Right edge
......@@ -90,8 +92,16 @@ function dragging(pos, duration) {
(pos.x + scrollView.flickableItem.contentX) / timeline.scaleFactor)
}
if (timeline.snap) {
for (i = 0; i < tracksRepeater.count; i++)
tracksRepeater.itemAt(i).snapDrop(pos)
var frame = Math.round((pos.x + scrollView.flickableItem.contentX) / timeline.scaleFactor)
var snapped = timeline.requestBestSnapPos(frame, duration)
if (snapped > 0) {
dropTarget.x = snapped * timeline.scaleFactor - scrollView.flickableItem.contentX + headerWidth;
}
}
var frame = Math.round((dropTarget.x - headerWidth + scrollView.flickableItem.contentX ) / timeline.scaleFactor)
if (!timeline.allowMove(currentTrack, frame, duration)) {
dropTarget.x = oldPosX
dropTarget.y = oldPosY
}
}
}
......
......@@ -49,11 +49,11 @@ Rectangle {
height: root.height - ruler.height
y: ruler.height
x: headerWidth
property int track: 0
onEntered: {
if (drag.formats.indexOf('kdenlive/producerslist') >= 0) {
track = Logic.getTrackFromPos(drag.y)
if (track >= 0 && timeline.allowMove(track, drag.x / timeline.scaleFactor, drag.text)) {
var track = Logic.getTrackFromPos(drag.y)
var frame = Math.round((drag.x + scrollView.flickableItem.contentX) / timeline.scaleFactor)
if (track >= 0 && timeline.allowMove(track, frame, drag.text)) {
drag.acceptProposedAction()
} else {
drag.accepted = false
......@@ -315,7 +315,7 @@ Rectangle {
height: multitrack.trackHeight
opacity: 0.5
visible: false
Text {
/*Text {
anchors.fill: parent
anchors.leftMargin: 100
text: timeline.ripple? qsTr('Insert') : qsTr('Overwrite')
......@@ -323,7 +323,7 @@ Rectangle {
styleColor: 'white'
font.pixelSize: Math.min(Math.max(parent.height * 0.8, 15), 30)
verticalAlignment: Text.AlignVCenter
}
}*/
}
Rectangle {
......
......@@ -315,3 +315,19 @@ void TimelineWidget::deleteTrack(int tid)
{
qDebug()<<"Deleting track: "<<tid;
}
int TimelineWidget::requestBestSnapPos(int pos, int duration)
{
return m_model->requestBestSnapPos(pos, duration);
}
void TimelineWidget::gotoNextSnap()
{
setPosition(m_model->requestNextSnapPos(m_position));
}
void TimelineWidget::gotoPreviousSnap()
{
setPosition(m_model->requestPreviousSnapPos(m_position));
}
......@@ -132,6 +132,8 @@ public:
Q_INVOKABLE void insertClip(int tid, int position, QString xml);
void deleteSelectedClips();
Q_INVOKABLE int requestBestSnapPos(int pos, int duration);
Q_INVOKABLE void triggerAction(const QString &name);
/* @brief Returns the current tractor's producer, useful fo control seeking, playing, etc
......@@ -155,6 +157,9 @@ public:
/* @brief Remove a timeline track
*/
Q_INVOKABLE void deleteTrack(int tid);
void gotoNextSnap();
void gotoPreviousSnap();
protected:
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
......
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