if (m_speed == 1.0) m_clipName = clip->name();
else {
m_clipName = clip->name() + " - " + QString::number(m_speed * 100, 'f', 0) + '%';
- m_cropDuration = m_cropDuration * m_speed;
}
m_producer = clip->getId();
m_clipType = clip->clipType();
- m_cropStart = info.cropStart;
+ //m_cropStart = info.cropStart;
m_maxDuration = clip->maxDuration();
setAcceptDrops(true);
m_audioThumbReady = clip->audioThumbCreated();
ClipItem *duplicate = new ClipItem(m_clip, info, m_fps, m_speed, m_strobe);
if (m_clipType == IMAGE || m_clipType == TEXT) duplicate->slotSetStartThumb(m_startPix);
else {
- if (info.cropStart == m_cropStart) duplicate->slotSetStartThumb(m_startPix);
- if (info.cropStart + (info.endPos - info.startPos) == m_cropStart + m_cropDuration) duplicate->slotSetEndThumb(m_endPix);
+ if (info.cropStart == m_info.cropStart) duplicate->slotSetStartThumb(m_startPix);
+ if (info.cropStart + (info.endPos - info.startPos) == m_info.cropStart + (m_info.endPos - m_info.startPos)) duplicate->slotSetEndThumb(m_endPix);
}
//kDebug() << "// CLoning clip: " << (info.cropStart + (info.endPos - info.startPos)).frames(m_fps) << ", CURRENT end: " << (cropStart() + duration()).frames(m_fps);
duplicate->setEffectList(m_effectList);
bool modified = false;
int lastPos = -1;
double lastValue = -1;
- int start = m_cropStart.frames(m_fps);
- int end = (m_cropStart + m_cropDuration).frames(m_fps);
+ int start = cropStart().frames(m_fps);
+ int end = (cropStart() + cropDuration()).frames(m_fps);
foreach(const QString &str, keyframes) {
int pos = str.section(':', 0, 0).toInt();
double val = str.section(':', 1, 1).toDouble();
void ClipItem::setKeyframes(const int ix, const QString keyframes)
{
- QDomElement effect = effectAt(ix);
+ QDomElement effect = getEffectAt(ix);
if (effect.attribute("disabled") == "1") return;
QDomNodeList params = effect.elementsByTagName("parameter");
for (int i = 0; i < params.count(); i++) {
if (checkDuration && (m_maxDuration != m_clip->maxDuration())) {
m_maxDuration = m_clip->maxDuration();
if (m_clipType != IMAGE && m_clipType != TEXT && m_clipType != COLOR) {
- if (m_maxDuration != GenTime() && m_cropStart + m_cropDuration > m_maxDuration) {
+ if (m_maxDuration != GenTime() && m_info.cropStart + m_info.cropDuration > m_maxDuration) {
// Clip duration changed, make sure to stay in correct range
- if (m_cropStart > m_maxDuration) {
- m_cropStart = GenTime();
- m_cropDuration = qMin(m_cropDuration, m_maxDuration);
+ if (m_info.cropStart > m_maxDuration) {
+ m_info.cropStart = GenTime();
+ m_info.cropDuration = qMin(m_info.cropDuration, m_maxDuration);
updateRectGeometry();
} else {
- m_cropDuration = m_maxDuration;
+ m_info.cropDuration = m_maxDuration;
updateRectGeometry();
}
}
int channels = baseClip()->getProperty("channels").toInt();
if (scale != m_framePixelWidth)
m_audioThumbCachePic.clear();
- double cropLeft = m_cropStart.frames(m_fps);
+ double cropLeft = m_info.cropStart.frames(m_fps);
const int clipStart = mappedRect.x();
const int mappedStartPixel = painter->matrix().map(QPointF(startpixel + cropLeft, 0)).x() - clipStart;
const int mappedEndPixel = painter->matrix().map(QPointF(endpixel + cropLeft, 0)).x() - clipStart;
pen.setStyle(Qt::DotLine);
painter->setPen(pen);
for (; it != markers.end(); ++it) {
- pos = (*it).time() / m_speed - cropStart();
+ pos = GenTime((int)((*it).time().frames(m_fps) / m_speed + 0.5), m_fps) - cropStart();
if (pos > GenTime()) {
if (pos > cropDuration()) break;
QLineF l(rect().x() + pos.frames(m_fps), rect().y(), rect().x() + pos.frames(m_fps), rect().bottom());
OPERATIONTYPE ClipItem::operationMode(QPointF pos)
{
if (isItemLocked()) return NONE;
-
+ const double scale = projectScene()->scale().x();
+ double maximumOffset = 6 / scale;
if (isSelected() || (parentItem() && parentItem()->isSelected())) {
- m_editedKeyframe = mouseOverKeyFrames(pos);
+ m_editedKeyframe = mouseOverKeyFrames(pos, maximumOffset);
if (m_editedKeyframe != -1) return KEYFRAME;
}
QRectF rect = sceneBoundingRect();
- const double scale = projectScene()->scale().x();
- double maximumOffset = 6 / scale;
int addtransitionOffset = 10;
// Don't allow add transition if track height is very small
if (rect.height() < 30) addtransitionOffset = 0;
GenTime pos;
for (int i = 0; i < markers.size(); i++) {
- pos = markers.at(i) / m_speed - cropStart();
+
+ pos = GenTime((int)(markers.at(i).frames(m_fps) / m_speed + 0.5), m_fps) - cropStart();
if (pos > GenTime()) {
if (pos > cropDuration()) break;
else snaps.append(pos + startPos());
GenTime pos;
for (int i = 0; i < markers.size(); i++) {
- pos = markers.at(i).time() / m_speed - cropStart();
+ pos = GenTime((int)(markers.at(i).time().frames(m_fps) / m_speed + 0.5), m_fps) - cropStart();
if (pos > GenTime()) {
if (pos > cropDuration()) break;
else snaps.append(CommentedTime(pos + startPos(), markers.at(i).comment()));
if (pos == m_startFade) return;
int oldIn = m_startFade;
if (pos < 0) pos = 0;
- if (pos > m_cropDuration.frames(m_fps)) pos = (int)(m_cropDuration.frames(m_fps));
+ if (pos > cropDuration().frames(m_fps)) pos = (int)(cropDuration().frames(m_fps));
m_startFade = pos;
QRectF rect = boundingRect();
update(rect.x(), rect.y(), qMax(oldIn, pos), rect.height());
if (pos == m_endFade) return;
int oldOut = m_endFade;
if (pos < 0) pos = 0;
- if (pos > m_cropDuration.frames(m_fps)) pos = (int)(m_cropDuration.frames(m_fps));
+ if (pos > cropDuration().frames(m_fps)) pos = (int)(cropDuration().frames(m_fps));
m_endFade = pos;
QRectF rect = boundingRect();
update(rect.x() + rect.width() - qMax(oldOut, pos), rect.y(), qMax(oldOut, pos), rect.height());
const int previous = cropStart().frames(m_fps);
AbstractClipItem::resizeStart(posx, m_speed);
if ((int) cropStart().frames(m_fps) != previous) {
- checkEffectsKeyframesPos(previous, cropStart().frames(m_fps), true);
if (m_hasThumbs && KdenliveSettings::videothumbnails()) {
/*connect(m_clip->thumbProducer(), SIGNAL(thumbReady(int, QPixmap)), this, SLOT(slotThumbReady(int, QPixmap)));*/
m_startThumbTimer.start(150);
}
}
-void ClipItem::resizeEnd(int posx, double /*speed*/, bool updateKeyFrames)
+void ClipItem::resizeEnd(int posx, double /*speed*/)
{
const int max = (startPos() - cropStart() + maxDuration()).frames(m_fps);
if (posx > max && maxDuration() != GenTime()) posx = max;
if (posx == endPos().frames(m_fps)) return;
//kDebug() << "// NEW POS: " << posx << ", OLD END: " << endPos().frames(m_fps);
- const int previous = (cropStart() + cropDuration()).frames(m_fps);
+ const int previous = (int)(cropStart() + cropDuration()).frames(m_fps) - 1;
AbstractClipItem::resizeEnd(posx, m_speed);
- if ((int)(cropStart() + cropDuration()).frames(m_fps) != previous) {
- if (updateKeyFrames) checkEffectsKeyframesPos(previous, (cropStart() + cropDuration()).frames(m_fps), false);
+ const int current = (int)(cropStart() + cropDuration()).frames(m_fps) - 1;
+ if (current != previous) {
if (m_hasThumbs && KdenliveSettings::videothumbnails()) {
/*connect(m_clip->thumbProducer(), SIGNAL(thumbReady(int, QPixmap)), this, SLOT(slotThumbReady(int, QPixmap)));*/
m_endThumbTimer.start(150);
}
-void ClipItem::checkEffectsKeyframesPos(const int previous, const int current, bool fromStart)
+bool ClipItem::checkEffectsKeyframesPos(const int previous, const int current, bool fromStart)
{
+ bool modified = false;
for (int i = 0; i < m_effectList.count(); i++) {
QDomElement effect = m_effectList.at(i);
QDomNodeList params = effect.elementsByTagName("parameter");
foreach(const QString &str, keyframes) {
pos = str.section(':', 0, 0).toInt();
val = str.section(':', 1, 1).toDouble();
- if (pos == previous) kfr[current] = val;
- else {
- if (fromStart && pos >= current) kfr[pos] = val;
- else if (!fromStart && pos <= current) kfr[pos] = val;
+ if (pos == previous) {
+ kfr[current] = val;
+ modified = true;
+ } else {
+ if ((fromStart && pos >= current) || (!fromStart && pos <= current)) {
+ kfr[pos] = val;
+ modified = true;
+ }
}
}
- QString newkfr;
- QMap<int, double>::const_iterator k = kfr.constBegin();
- while (k != kfr.constEnd()) {
- newkfr.append(QString::number(k.key()) + ':' + QString::number(k.value()) + ';');
- ++k;
+ if (modified) {
+ QString newkfr;
+ QMap<int, double>::const_iterator k = kfr.constBegin();
+ while (k != kfr.constEnd()) {
+ newkfr.append(QString::number(k.key()) + ':' + QString::number(k.value()) + ';');
+ ++k;
+ }
+ e.setAttribute("keyframes", newkfr);
+ break;
}
- e.setAttribute("keyframes", newkfr);
- break;
}
}
}
- if (m_selectedEffect >= 0) setSelectedEffect(m_selectedEffect);
+ if (modified && m_selectedEffect >= 0) setSelectedEffect(m_selectedEffect);
+ return modified;
}
//virtual
subitems.removeAll(this);
for (int j = 0; j < subitems.count(); j++) {
if (subitems.at(j)->type() == type()) {
- m_startPos = GenTime((int) pos().x(), m_fps);
+ m_info.startPos = GenTime((int) pos().x(), m_fps);
return pos();
}
}
}
- m_track = newTrack;
- m_startPos = GenTime((int) newPos.x(), m_fps);
+ m_info.track = newTrack;
+ m_info.startPos = GenTime((int) newPos.x(), m_fps);
return newPos;
}
}
}
- m_track = newTrack;
- m_startPos = GenTime((int) newPos.x(), m_fps);
+ m_info.track = newTrack;
+ m_info.startPos = GenTime((int) newPos.x(), m_fps);
//kDebug()<<"// ITEM NEW POS: "<<newPos.x()<<", mapped: "<<mapToScene(newPos.x(), 0).x();
return newPos;
}
}
//kDebug() << "CHange EFFECT AT: " << ix << ", CURR: " << m_effectList.at(ix).attribute("tag") << ", NEW: " << effect.attribute("tag");
effect.setAttribute("kdenlive_ix", ix + 1);
- m_effectList.insert(ix, effect);
- m_effectList.removeAt(ix + 1);
+ m_effectList.replace(ix, effect);
m_effectNames = m_effectList.effectNames().join(" / ");
QString id = effect.attribute("id");
if (id == "fadein" || id == "fadeout" || id == "fade_from_black" || id == "fade_to_black")
EffectsParameterList ClipItem::addEffect(const QDomElement effect, bool animate)
{
bool needRepaint = false;
- int ix = effect.attribute("kdenlive_ix").toInt();
- if (ix <= m_effectList.count()) {
+ int ix;
+ if (!effect.hasAttribute("kdenlive_ix")) {
+ ix = effectsCounter();
+ } else ix = effect.attribute("kdenlive_ix").toInt();
+ if (!m_effectList.isEmpty() && ix <= m_effectList.count()) {
needRepaint = true;
m_effectList.insert(ix - 1, effect);
for (int i = ix; i < m_effectList.count(); i++) {
m_effectNames = m_effectList.effectNames().join(" / ");
if (fade > 0) m_startFade = fade;
else if (fade < 0) m_endFade = -fade;
+
if (m_selectedEffect == -1) {
setSelectedEffect(0);
- }
+ } else if (m_selectedEffect == ix - 1) setSelectedEffect(m_selectedEffect);
if (needRepaint) update(boundingRect());
/*if (animate) {
flashClip();
}
}
m_effectNames = m_effectList.effectNames().join(" / ");
+
if (m_effectList.isEmpty() || m_selectedEffect + 1 == index.toInt()) {
// Current effect was removed
if (index.toInt() > m_effectList.count() - 1) {
} else setSelectedEffect(index.toInt());
}
if (needRepaint) update(boundingRect());
- if (!m_effectList.isEmpty()) flashClip();
+ else {
+ QRectF r = boundingRect();
+ r.setHeight(20);
+ update(r);
+ }
+ //if (!m_effectList.isEmpty()) flashClip();
}
double ClipItem::speed() const
GenTime ClipItem::maxDuration() const
{
- return m_maxDuration / m_speed;
+ return GenTime((int)(m_maxDuration.frames(m_fps) / m_speed + 0.5), m_fps);
}
GenTime ClipItem::cropStart() const
{
- return m_cropStart / m_speed;
+ return GenTime((int)(m_info.originalcropStart.frames(m_fps) / m_speed + 0.5), m_fps);
}
GenTime ClipItem::cropDuration() const
{
- return m_cropDuration / m_speed;
+ return GenTime((int)(m_info.cropDuration.frames(m_fps) / m_speed + 0.5), m_fps);
}
GenTime ClipItem::endPos() const
{
- return m_startPos + cropDuration();
+ return m_info.startPos + cropDuration();
}
//virtual
if (scene() && !scene()->views().isEmpty()) {
event->accept();
CustomTrackView *view = (CustomTrackView *) scene()->views()[0];
- if (view) view->slotAddEffect(e, m_startPos, track());
+ if (view) view->slotAddEffect(e, m_info.startPos, track());
}
}