Commit a778c90c authored by Jason Wood's avatar Jason Wood

Factored snap to grid functionality into a seperate class; this can now be...

Factored snap to grid functionality into a seperate class; this can now be used on a case-by-case basis for each trackpanel tool function.

svn path=/trunk/kdenlive/; revision=233
parent e6ab0722
/***************************************************************************
snaptogrid.cpp - description
-------------------
begin : Fri May 9 2003
copyright : (C) 2003 by Jason Wood
email : jasonwood@blueyonder.co.uk
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "gentime.h"
#include "snaptogrid.h"
#include "qptrlist.h"
#include "qvaluelist.h"
SnapToGrid::SnapToGrid(KdenliveDoc *doc) :
m_document(doc),
m_isDirty(true)
{
m_internalSnapTracker = m_internalSnapList.end();
}
SnapToGrid::~SnapToGrid()
{
}
/**
Add and set seek times. A seek time is a time that we wish to snap to, but
which is independant of the clip borders.
*/
uint SnapToGrid::addSeekTime(const GenTime &seekTime)
{
m_seekTimes.append(seekTime);
if(snapToSeekTime()) setDirty(true);
return m_seekTimes.count()-1;
}
void SnapToGrid::setSeekTime(uint index, const GenTime &seekTime)
{
if(index < m_seekTimes.count()) {
m_seekTimes[index] = seekTime;
if(snapToSeekTime()) setDirty(true);
}
}
/**
get/set whether or not clip start times are snapped to
*/
void SnapToGrid::setSnapToClipStart(bool snapToClipStart)
{
if(m_snapToClipStart != snapToClipStart) {
m_snapToClipStart = snapToClipStart;
setDirty(true);
}
}
bool SnapToGrid::snapToClipStart() const
{
return m_snapToClipStart;
}
void SnapToGrid::setIncludeSelectedClips(bool includeSelectedClips)
{
if(m_includeSelectedClips != includeSelectedClips) {
m_includeSelectedClips = includeSelectedClips;
setDirty(true);
}
}
bool SnapToGrid::includeSelectedClips() const
{
return m_includeSelectedClips;
}
/**
get/set whether or not clip end times are snapped to
*/
void SnapToGrid::setSnapToClipEnd(bool snapToClipEnd)
{
if(m_snapToClipEnd != snapToClipEnd) {
m_snapToClipEnd = snapToClipEnd;
setDirty(true);
}
}
bool SnapToGrid::snapToClipEnd() const
{
return m_snapToClipEnd;
}
/**
get/set whether or not seek times are snapped to
*/
void SnapToGrid::setSnapToSeekTime(bool snapToSeekTime)
{
if(m_snapToSeekTime != snapToSeekTime) {
m_snapToSeekTime = snapToSeekTime;
setDirty(true);
}
}
bool SnapToGrid::snapToSeekTime() const
{
return m_snapToSeekTime;
}
/**
Get/set snapToFrame value. If true, then any returned time will snap to the
current frame.
*/
void SnapToGrid::setSnapToFrame(bool snapToFrame)
{
if(m_snapToFrame != snapToFrame)
{
m_snapToFrame = snapToFrame;
setDirty(true);
}
}
bool SnapToGrid::snapToFrame() const
{
return m_snapToFrame;
}
/**
Sets the cursor times to the specified list. Each cursor time is individually
'snapped' to the list of snap times when calculating the final snap.
*/
void SnapToGrid::setCursorTimes(const QValueList<GenTime> & time)
{
m_cursorTimes = time;
}
void SnapToGrid::setDirty(bool dirty)
{
m_isDirty = dirty;
}
bool SnapToGrid::isDirty() const
{
return m_isDirty;
}
void SnapToGrid::setSnapTolerance(const GenTime &tolerance)
{
m_snapTolerance = tolerance;
}
const GenTime &SnapToGrid::snapTolerance() const
{
return m_snapTolerance;
}
/**
Returns a snapped time compared to the specified GenTime. In the case of their being
multiple cursors, it is assumed that the time specified is that which the first
cursor time in the list will move to. The returned time takes into account clip
begin/end times (if they are turned on), seek times (if they are turned on), and
frame borders (if they are turned on).
*/
GenTime SnapToGrid::getSnappedTime(const GenTime &time) const
{
GenTime result = time;
if(isDirty()) {
createInternalSnapList();
m_isDirty = false;
}
if(m_internalSnapTracker != m_internalSnapList.end()) {
QValueListConstIterator<GenTime> itt = m_internalSnapTracker;
++itt;
while(itt != m_internalSnapList.end()) {
double newTime = fabs(((*itt) - time).seconds());
double oldTime = fabs(((*m_internalSnapTracker) - time).seconds());
if ( newTime > oldTime ) break;
m_internalSnapTracker = itt;
++itt;
}
itt = m_internalSnapTracker;
--itt;
while(m_internalSnapTracker != m_internalSnapList.begin()) {
double newTime = fabs(((*itt) - time).seconds());
double oldTime = fabs(((*m_internalSnapTracker) - time).seconds());
if(newTime > oldTime) break;
m_internalSnapTracker = itt;
--itt;
}
double diff = fabs(((*m_internalSnapTracker) - result).seconds());
if(diff < m_snapTolerance.seconds()) {
result = *m_internalSnapTracker;
}
}
if(m_snapToFrame) {
result = GenTime((int)floor(result.frames(m_document->framesPerSecond())+0.5), m_document->framesPerSecond());
}
return result;
}
void SnapToGrid::createInternalSnapList() const
{
m_internalSnapList.clear();
m_internalSnapTracker = m_internalSnapList.begin();
if(m_cursorTimes.count() == 0) return;
QValueList<GenTime> list = snapToGridList();
// For each cursor time, append a correct snap time to the list.
// This is calculated as follows : masterClipTime + required snap time - cursor time.
QValueListConstIterator<GenTime> cursorItt = m_cursorTimes.begin();
while(cursorItt != m_cursorTimes.end())
{
QValueListIterator<GenTime> timeItt = list.begin();
while(timeItt != list.end()) {
m_internalSnapList.append(m_cursorTimes[0] + (*timeItt) - (*cursorItt));
++timeItt;
}
++cursorItt;
}
qHeapSort(m_internalSnapList);
QValueListIterator<GenTime> itt = m_internalSnapList.begin();
if(itt != m_internalSnapList.end()) {
QValueListIterator<GenTime> next = itt;
++next;
while(next != m_internalSnapList.end()) {
if((*itt) == (*next)) {
m_internalSnapList.remove(next);
next = itt;
++next;
} else {
++itt;
++next;
}
}
}
m_internalSnapTracker = m_internalSnapList.begin();
}
QValueList<GenTime> SnapToGrid::snapToGridList() const
{
QValueList<GenTime> list;
// Add snap to seek positions.
if(m_snapToSeekTime) {
list = m_seekTimes;
}
// Add all trackStart/trackEnd points to the list as appropriate.
for(uint count=0; count<m_document->numTracks(); ++count)
{
QPtrListIterator<DocClipBase> clipItt = m_document->track(count)->firstClip(false);
while(clipItt.current()) {
if(m_snapToClipStart) list.append(clipItt.current()->trackStart());
if(m_snapToClipEnd) list.append(clipItt.current()->trackEnd());
++clipItt;
}
if(m_includeSelectedClips) {
clipItt = m_document->track(count)->firstClip(true);
while(clipItt.current()) {
if(m_snapToClipStart) list.append(clipItt.current()->trackStart());
if(m_snapToClipEnd) list.append(clipItt.current()->trackEnd());
++clipItt;
}
}
}
return list;
}
void SnapToGrid::prependCursor(const GenTime &cursor)
{
m_cursorTimes.prepend(cursor);
setDirty(true);
}
void SnapToGrid::appendCursor(const GenTime &cursor)
{
m_cursorTimes.append(cursor);
setDirty(true);
}
void SnapToGrid::clearSeekTimes()
{
m_seekTimes.clear();
if(m_snapToSeekTime) {
setDirty(true);
}
}
/***************************************************************************
snaptogrid.h - description
-------------------
begin : Fri May 9 2003
copyright : (C) 2003 by Jason Wood
email : jasonwood@blueyonder.co.uk
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef SNAPTOGRID_H
#define SNAPTOGRID_H
#include <kdenlivedoc.h>
/**
Manages snap to grid times. Allows the getting and setting of various times
including seek positions, clip start and end times, and various others.
@author Jason Wood
*/
class SnapToGrid
{
public:
SnapToGrid(KdenliveDoc *doc);
~SnapToGrid();
/**
Add and set seek times. A seek time is a time that we wish to snap to, but
which is independant of the clip borders.
*/
uint addSeekTime(const GenTime &seekTime);
void setSeekTime(uint index, const GenTime &seekTime);
/** Clear all seek times */
void clearSeekTimes();
/**
get/set whether or not clip start times are snapped to
*/
void setSnapToClipStart(bool snapToClipStart);
bool snapToClipStart() const;
/**
get/set whether or not clip end times are snapped to
*/
void setSnapToClipEnd(bool snapToClipEnd);
bool snapToClipEnd() const;
/**
get/set whether or not selected clips are included with unselected clips.
*/
void setIncludeSelectedClips(bool includeSelectedClips);
bool includeSelectedClips() const;
/**
get/set whether or not seek times are snapped to
*/
void setSnapToSeekTime(bool snapToSeekTime);
bool snapToSeekTime() const;
/**
Get/set snapToFrame value. If true, then any returned time will snap to the
current frame.
*/
void setSnapToFrame(bool snapToFrame);
bool snapToFrame() const;
/**
Sets the cursor times to the specified list. Each cursor time is individually
'snapped' to the list of snap times when calculating the final snap.
*/
void setCursorTimes(const QValueList<GenTime> & time);
/**
Adds a new cursor time at the beginning of the cursor list.
*/
void prependCursor(const GenTime &cursor);
/**
Adds a new cursor time at the end of the cursor list.
*/
void appendCursor(const GenTime &cursor);
/**
Get/Set the snap tolerance. This is the time interval that we must be withing before
we snap to a a given point.
*/
void setSnapTolerance(const GenTime &tolerance);
const GenTime &snapTolerance() const;
/**
Returns a snapped time compared to the specified GenTime. In the case of their being
multiple cursors, it is assumed that the time specified is that which the first
cursor time in the list will move to. The returned time takes into account clip
begin/end times (if they are turned on), seek times (if they are turned on), and
frame borders (if they are turned on).
*/
GenTime getSnappedTime(const GenTime &time) const;
private:
KdenliveDoc *m_document;
QValueList<GenTime> m_seekTimes;
QValueList<GenTime> m_cursorTimes;
bool m_snapToFrame;
bool m_snapToClipStart;
bool m_snapToClipEnd;
bool m_includeSelectedClips;
bool m_snapToSeekTime;
GenTime m_snapTolerance;
/** A list of all times that are "snapToGrid" times. Generated specifically for a
particular set of cursor times, this list of times is the only thing we need to
consult when checkinga time to determine when we need to snap to a particular
location based upon another clip. */
mutable QValueList<GenTime> m_internalSnapList;
/** Keeps track of whichever list item is closest to the mouse cursor. */
mutable QValueListConstIterator<GenTime> m_internalSnapTracker;
mutable bool m_isDirty;
private: // methods
/**
For efficiency reason, we only want to update the internal snap lists when it is
absolutely necessary. So we keep track of when an important change has happened,
and then only update the snap list when the next request for data is made.
*/
void setDirty(bool dirty);
bool isDirty() const;
/** Creates a list of all snap points for the timeline. This includes the current seek
position, the beginning of the timeline, and the start and end points of every clip in
the document */
QValueList<GenTime> snapToGridList() const;
/** Generates the internal snap list. See m_snapToGridList for more details.*/
void createInternalSnapList() const;
};
#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