aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Baptiste Mardelle <[email protected]>2015-06-07 21:39:15 +0200
committerJean-Baptiste Mardelle <[email protected]>2015-06-07 21:39:15 +0200
commitaaf2819f771e6cfa7c7b9d404c1c5ddea545c7be (patch)
tree97f81f22ffb80e82e09c40f04fb57e0b97cd314a
parentcc55a9cea5c2f029744f8aba79a362fd302ec0bb (diff)
Some polish for geometry effect ui, geometry keyframe now appear in timeline clips and can be moved
-rw-r--r--src/doc/kdenlivedoc.cpp2
-rw-r--r--src/effectstack/keyframehelper.cpp110
-rw-r--r--src/effectstack/keyframehelper.h3
-rw-r--r--src/project/projectmanager.cpp15
-rw-r--r--src/project/projectmanager.h4
-rw-r--r--src/timeline/abstractclipitem.cpp50
-rw-r--r--src/timeline/abstractclipitem.h14
-rw-r--r--src/timeline/clipitem.cpp111
-rw-r--r--src/timeline/clipitem.h4
-rw-r--r--src/ui/geometrywidget_ui.ui45
10 files changed, 213 insertions, 145 deletions
diff --git a/src/doc/kdenlivedoc.cpp b/src/doc/kdenlivedoc.cpp
index 467c628..be52013 100644
--- a/src/doc/kdenlivedoc.cpp
+++ b/src/doc/kdenlivedoc.cpp
@@ -607,7 +607,7 @@ void KdenliveDoc::slotAutoSave(QMap <double, QString> guidesData)
if (m_render && m_autosave) {
if (!m_autosave->isOpen() && !m_autosave->open(QIODevice::ReadWrite)) {
// show error: could not open the autosave file
- //qDebug() << "ERROR; CANNOT CREATE AUTOSAVE FILE";
+ qDebug() << "ERROR; CANNOT CREATE AUTOSAVE FILE";
}
//qDebug() << "// AUTOSAVE FILE: " << m_autosave->fileName();
QDomDocument sceneList = xmlSceneList(m_render->sceneList(), guidesData);
diff --git a/src/effectstack/keyframehelper.cpp b/src/effectstack/keyframehelper.cpp
index f5ca282..8e03178 100644
--- a/src/effectstack/keyframehelper.cpp
+++ b/src/effectstack/keyframehelper.cpp
@@ -32,7 +32,6 @@
#include <QApplication>
const int margin = 5;
-const int cursorWidth = 6;
#define SEEK_INACTIVE (-1)
@@ -44,18 +43,19 @@ KeyframeHelper::KeyframeHelper(QWidget *parent) :
, m_scale(0)
, m_movingKeyframe(false)
, m_movingItem()
- , m_lineHeight(9)
- , m_drag(false)
, m_hoverKeyframe(-1)
, m_seekPosition(SEEK_INACTIVE)
{
setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
setMouseTracking(true);
QPalette p = palette();
+ m_size = QFontInfo(font()).pixelSize() * 1.8;
+ m_lineHeight = m_size / 2;
+ setMinimumHeight(m_size);
+ setMaximumHeight(m_size);
KColorScheme scheme(p.currentColorGroup(), KColorScheme::Window, KSharedConfig::openConfig(KdenliveSettings::colortheme()));
m_selected = scheme.decoration(KColorScheme::HoverColor).color();
m_keyframe = scheme.foreground(KColorScheme::LinkText).color();
- m_keyframebg = scheme.shade(KColorScheme::MidShade);
}
// virtual
@@ -67,13 +67,13 @@ void KeyframeHelper::mousePressEvent(QMouseEvent * event)
return;
}
int xPos = event->x() - margin;
- if (m_geom != NULL && (event->y() < m_lineHeight)) {
+ int headOffset = m_lineHeight / 1.5;
+ if (m_geom != NULL && (event->y() <= headOffset)) {
// check if we want to move a keyframe
int mousePos = qMax((int)(xPos / m_scale), 0);
Mlt::GeometryItem item;
if (m_geom->next_key(&item, mousePos) == 0) {
- if (qAbs(item.frame() * m_scale - xPos) < 4) {
- m_drag = true;
+ if (qAbs(item.frame() * m_scale - xPos) < headOffset) {
m_movingItem.x(item.x());
m_movingItem.y(item.y());
m_movingItem.w(item.w());
@@ -95,21 +95,16 @@ void KeyframeHelper::mousePressEvent(QMouseEvent * event)
m_extraMovingItems.append(NULL);
}
}
-
m_dragStart = event->pos();
- m_movingKeyframe = true;
return;
}
}
}
- if (event->y() >= m_lineHeight && event->y() < height()) {
- int seekRequest = xPos / m_scale;
- m_drag = true;
- if (seekRequest != m_position) {
- m_seekPosition = seekRequest;
- emit requestSeek(m_seekPosition);
- update();
- }
+ int seekRequest = xPos / m_scale;
+ if (seekRequest != m_position) {
+ m_seekPosition = seekRequest;
+ emit requestSeek(m_seekPosition);
+ update();
}
}
@@ -126,9 +121,10 @@ void KeyframeHelper::leaveEvent( QEvent * event )
void KeyframeHelper::mouseMoveEvent(QMouseEvent * event)
{
int xPos = event->x() - margin;
- if (!m_drag) {
+ int headOffset = m_lineHeight / 1.5;
+ if (event->buttons() == Qt::NoButton) {
int mousePos = qMax((int)(xPos / m_scale), 0);
- if (qAbs(m_position * m_scale - xPos) < cursorWidth && event->y() >= m_lineHeight) {
+ if (qAbs(m_position * m_scale - xPos) < m_lineHeight && event->y() >= m_lineHeight) {
// Mouse over time cursor
if (m_hoverKeyframe != -2) {
m_hoverKeyframe = -2;
@@ -141,7 +137,7 @@ void KeyframeHelper::mouseMoveEvent(QMouseEvent * event)
// check if we want to move a keyframe
Mlt::GeometryItem item;
if (m_geom->next_key(&item, mousePos) == 0) {
- if (qAbs(item.frame() * m_scale - xPos) < 4) {
+ if (qAbs(item.frame() * m_scale - xPos) < headOffset) {
if (m_hoverKeyframe == item.frame()) return;
m_hoverKeyframe = item.frame();
setCursor(Qt::PointingHandCursor);
@@ -159,16 +155,17 @@ void KeyframeHelper::mouseMoveEvent(QMouseEvent * event)
event->accept();
return;
}
- if (m_movingKeyframe) {
- if (!m_dragStart.isNull()) {
+ if (!m_dragStart.isNull() || m_movingKeyframe) {
+ if (!m_movingKeyframe) {
if ((QPoint(xPos, event->y()) - m_dragStart).manhattanLength() < QApplication::startDragDistance()) return;
+ m_movingKeyframe = true;
m_dragStart = QPoint();
m_geom->remove(m_movingItem.frame());
for (int i = 0; i < m_extraGeometries.count(); ++i)
m_extraGeometries[i]->remove(m_movingItem.frame());
}
int pos = qBound(0, (int)(xPos / m_scale), frameLength);
- if (KdenliveSettings::snaptopoints() && qAbs(pos - m_position) < 5)
+ if (KdenliveSettings::snaptopoints() && qAbs(pos - m_position) < headOffset)
pos = m_position;
m_movingItem.frame(pos);
for (int i = 0; i < m_extraMovingItems.count(); ++i) {
@@ -206,7 +203,6 @@ void KeyframeHelper::mouseDoubleClickEvent(QMouseEvent * event)
// virtual
void KeyframeHelper::mouseReleaseEvent(QMouseEvent * event)
{
- m_drag = false;
setCursor(Qt::ArrowCursor);
m_hoverKeyframe = -1;
if (m_movingKeyframe) {
@@ -217,10 +213,15 @@ void KeyframeHelper::mouseReleaseEvent(QMouseEvent * event)
if (m_extraMovingItems.at(i))
m_extraGeometries[i]->insert(m_extraMovingItems.at(i));
}
-
+ m_movingKeyframe = false;
emit keyframeMoved(m_position);
return;
}
+ else if (!m_dragStart.isNull()) {
+ m_seekPosition = m_movingItem.frame();
+ m_dragStart = QPoint();
+ emit requestSeek(m_seekPosition);
+ }
QWidget::mouseReleaseEvent(event);
}
@@ -245,72 +246,59 @@ void KeyframeHelper::wheelEvent(QWheelEvent * e)
// virtual
void KeyframeHelper::paintEvent(QPaintEvent *e)
{
- QStylePainter p(this);
+ QPainter p(this);
+ p.setRenderHints(QPainter::Antialiasing);
const QRectF clipRect = e->rect();
p.setClipRect(clipRect);
m_scale = (double) (width() - 2 * margin) / frameLength;
+ int headOffset = m_lineHeight / 1.5;
if (m_geom != NULL) {
int pos = 0;
- p.setPen(m_keyframe);
- p.setBrush(m_keyframebg);
Mlt::GeometryItem item;
while (true) {
if (m_geom->next_key(&item, pos) == 1) break;
pos = item.frame();
- if (pos == m_hoverKeyframe) {
- p.setBrush(m_selected);
- }
int scaledPos = margin + pos * m_scale;
// draw keyframes
- p.drawLine(scaledPos, 9, scaledPos, 15);
- // draw pointer
- QPolygon pa(4);
- pa.setPoints(4,
- scaledPos, 0,
- scaledPos - 4, 4,
- scaledPos, 8,
- scaledPos + 4, 4);
- p.drawPolygon(pa);
- //p.drawEllipse(scaledPos - 4, 0, 8, 8);
- if (pos == m_hoverKeyframe) {
- p.setBrush(m_keyframebg);
+ if (pos == m_position || pos == m_hoverKeyframe) {
+ // active keyframe
+ p.setBrush(m_selected);
+ p.setPen(m_selected);
}
- //p.fillRect(QRect(scaledPos - 1, 0, 2, 15), QBrush(QColor(255, 20, 20)));
+ else {
+ p.setPen(palette().text().color());
+ p.setBrush(palette().text());
+ }
+ p.drawLine(scaledPos, headOffset, scaledPos, m_size);
+ p.drawEllipse(scaledPos - headOffset / 2, 0, headOffset, headOffset);
pos++;
}
-
if (m_movingKeyframe) {
p.setBrush(m_selected);
int scaledPos = margin + (int)(m_movingItem.frame() * m_scale);
// draw keyframes
- p.drawLine(scaledPos, 9, scaledPos, 15);
- // draw pointer
- QPolygon pa(5);
- pa.setPoints(4,
- scaledPos, 0,
- scaledPos - 4, 4,
- scaledPos, 8,
- scaledPos + 4, 4);
- p.drawPolygon(pa);
+ p.drawLine(scaledPos, headOffset, scaledPos, m_size);
+ p.drawEllipse(scaledPos - headOffset / 2, 0, headOffset, headOffset);
p.setBrush(m_keyframe);
}
}
- p.setPen(palette().dark().color());
- p.drawLine(margin, m_lineHeight, width() - margin - 1, m_lineHeight);
- p.drawLine(margin, m_lineHeight - 3, margin, m_lineHeight + 3);
- p.drawLine(width() - margin, m_lineHeight - 3, width() - margin, m_lineHeight + 3);
-
+ p.setPen(palette().text().color());
+ p.drawLine(margin, m_lineHeight + (headOffset / 2), width() - margin - 1, m_lineHeight + (headOffset / 2));
+ p.drawLine(margin, m_lineHeight - headOffset, margin, m_lineHeight + headOffset);
+ p.drawLine(width() - margin, m_lineHeight - headOffset, width() - margin, m_lineHeight + headOffset);
+ p.setPen(Qt::NoPen);
// draw pointer
if (m_seekPosition != SEEK_INACTIVE) {
p.fillRect(margin + m_seekPosition * m_scale - 1, 0, 3, height(), palette().dark());
}
QPolygon pa(3);
const int cursor = margin + m_position * m_scale;
- pa.setPoints(3, cursor - cursorWidth, 16, cursor + cursorWidth, 16, cursor, 10);
+ int cursorwidth = (m_size - (m_lineHeight + headOffset / 2)) / 2 + 1;
+ pa.setPoints(3, cursor - cursorwidth, m_size, cursor + cursorwidth, m_size, cursor, m_lineHeight + (headOffset / 2) + 1);
if (m_hoverKeyframe == -2)
p.setBrush(palette().highlight());
else
- p.setBrush(palette().dark().color());
+ p.setBrush(palette().text());
p.drawPolygon(pa);
}
diff --git a/src/effectstack/keyframehelper.h b/src/effectstack/keyframehelper.h
index 701609b..0bc34c6 100644
--- a/src/effectstack/keyframehelper.h
+++ b/src/effectstack/keyframehelper.h
@@ -47,17 +47,16 @@ protected:
private:
Mlt::Geometry *m_geom;
int m_position;
+ int m_size;
double m_scale;
bool m_movingKeyframe;
Mlt::GeometryItem m_movingItem;
QList <Mlt::GeometryItem *> m_extraMovingItems;
QPoint m_dragStart;
int m_lineHeight;
- bool m_drag;
int m_hoverKeyframe;
QColor m_selected;
QColor m_keyframe;
- QColor m_keyframebg;
QList <Mlt::Geometry *>m_extraGeometries;
int m_seekPosition;
diff --git a/src/project/projectmanager.cpp b/src/project/projectmanager.cpp
index eac2918..d6876b2 100644
--- a/src/project/projectmanager.cpp
+++ b/src/project/projectmanager.cpp
@@ -163,6 +163,7 @@ void ProjectManager::newFile(bool showProjectSettings, bool force)
pCore->window()->connectDocument();
emit docOpened(m_project);
pCore->monitorManager()->activateMonitor(Kdenlive::ClipMonitor);
+ m_lastSave.start();
}
bool ProjectManager::closeCurrentDocument(bool saveChanges)
@@ -284,7 +285,7 @@ void ProjectManager::openFile()
{
if (m_startUrl.isValid()) {
openFile(m_startUrl);
- m_startUrl = QUrl();
+ m_startUrl.clear();
return;
}
//TODO KF5 set default location to project folder
@@ -427,7 +428,6 @@ void ProjectManager::doOpenFile(const QUrl &url, KAutoSaveFile *stale)
progressDialog.setMaximum(4);
progressDialog.setValue(1);
progressDialog.repaint();
-
if (stale == NULL) {
stale = new KAutoSaveFile(url, doc);
doc->m_autosave = stale;
@@ -478,6 +478,7 @@ void ProjectManager::doOpenFile(const QUrl &url, KAutoSaveFile *stale)
if (openBackup) {
slotOpenBackup(url);
}
+ m_lastSave.start();
}
void ProjectManager::slotRevert()
@@ -545,12 +546,20 @@ KRecentFilesAction* ProjectManager::recentFilesAction()
void ProjectManager::slotStartAutoSave()
{
- m_autoSaveTimer.start(3000); // will trigger slotAutoSave() in 3 seconds
+ if (m_lastSave.elapsed() > 300000) {
+ // If the project was not saved in the last 5 minute, force save
+ m_autoSaveTimer.stop();
+ slotAutoSave();
+ }
+ else {
+ m_autoSaveTimer.start(3000); // will trigger slotAutoSave() in 3 seconds
+ }
}
void ProjectManager::slotAutoSave()
{
m_project->slotAutoSave(m_trackView->projectView()->guidesData());
+ m_lastSave.start();
}
diff --git a/src/project/projectmanager.h b/src/project/projectmanager.h
index 88d8f23..1f865c3 100644
--- a/src/project/projectmanager.h
+++ b/src/project/projectmanager.h
@@ -14,6 +14,7 @@ the Free Software Foundation, either version 3 of the License, or
#include <QObject>
#include <QUrl>
#include <QTimer>
+#include <QTime>
#include <KRecentFilesAction>
#include "kdenlivecore_export.h"
@@ -107,9 +108,8 @@ private:
KdenliveDoc *m_project;
Timeline *m_trackView;
-
+ QTime m_lastSave;
QTimer m_autoSaveTimer;
-
QUrl m_startUrl;
QString m_loadClipsOnOpen;
diff --git a/src/timeline/abstractclipitem.cpp b/src/timeline/abstractclipitem.cpp
index 567773f..6930086 100644
--- a/src/timeline/abstractclipitem.cpp
+++ b/src/timeline/abstractclipitem.cpp
@@ -253,7 +253,7 @@ GenTime AbstractClipItem::maxDuration() const
return m_maxDuration;
}
-void AbstractClipItem::drawKeyFrames(QPainter *painter, const QTransform &transformation, bool limitedKeyFrames)
+void AbstractClipItem::drawKeyFrames(QPainter *painter, const QTransform &transformation)
{
if (m_keyframes.count() < 1)
return;
@@ -263,13 +263,43 @@ void AbstractClipItem::drawKeyFrames(QPainter *painter, const QTransform &transf
double start = cropStart().frames(m_fps);
double x1, y1, x2, y2;
bool antialiasing = painter->renderHints() & QPainter::Antialiasing;
+ bool active = isSelected() || (parentItem() && parentItem()->isSelected());
+
+ // draw keyframes
+ QMap<int, int>::const_iterator i = m_keyframes.constBegin();
+ QColor color(Qt::blue);
+ QLineF l2;
+ painter->setPen(color);
+ // Special case: Geometry keyframes are just vertical lines
+ if (m_keyframeType == GeometryKeyframe) {
+ while (i != m_keyframes.constEnd()) {
+ if (active) {
+ if (i.key() == m_editedKeyframe)
+ color = QColor(Qt::red);
+ else
+ color = QColor(Qt::blue);
+ painter->setPen(color);
+ }
+ x1 = br.x() + maxw * (i.key() - start);
+ QLineF l(x1, br.top(), x1, br.height());
+ l2 = transformation.map(l);
+
+ painter->drawLine(l2);
+ if (active) {
+ const QRectF frame(l2.x1() - 3, l2.y1() + (l2.y2() - l2.y1()) / 2 - 3, 6, 6);
+ painter->fillRect(frame, color);
+ }
+ ++i;
+ }
+ painter->setRenderHint(QPainter::Antialiasing, antialiasing);
+ return;
+ }
// draw line showing default value
- bool active = isSelected() || (parentItem() && parentItem()->isSelected());
if (active) {
x1 = br.x();
x2 = br.right();
- if (limitedKeyFrames) {
+ if (m_keyframeType == NormalKeyframe) {
QMap<int, int>::const_iterator end = m_keyframes.constEnd();
--end;
x2 = x1 + maxw * (end.key() - start);
@@ -286,17 +316,11 @@ void AbstractClipItem::drawKeyFrames(QPainter *painter, const QTransform &transf
painter->setRenderHint(QPainter::Antialiasing);
}
- // draw keyframes
- QMap<int, int>::const_iterator i = m_keyframes.constBegin();
- QColor color(Qt::blue);
- QLineF l2;
x1 = br.x() + maxw * (i.key() - start);
y1 = br.bottom() - (i.value() - m_keyframeOffset) * maxh;
-
-
// make sure line begins with clip beginning
- if (!limitedKeyFrames && i.key() != start) {
+ if (m_keyframeType != NormalKeyframe && i.key() != start) {
QLineF l(br.x(), y1, x1, y1);
l2 = transformation.map(l);
painter->drawLine(l2);
@@ -329,7 +353,7 @@ void AbstractClipItem::drawKeyFrames(QPainter *painter, const QTransform &transf
}
// make sure line ends at clip end
- if (!limitedKeyFrames && x1 != br.right()) {
+ if (m_keyframeType != NormalKeyframe && x1 != br.right()) {
QLineF l(x1, y1, br.right(), y1);
painter->drawLine(transformation.map(l));
}
@@ -351,7 +375,9 @@ int AbstractClipItem::mouseOverKeyFrames(QPointF pos, double maxOffset)
QMap<int, int>::const_iterator i = m_keyframes.constBegin();
while (i != m_keyframes.constEnd()) {
double x1 = br.x() + maxw * (i.key() - cropStart().frames(m_fps));
- double y1 = br.bottom() - (i.value() - m_keyframeOffset) * maxh;
+ double y1;
+ if (m_keyframeType == GeometryKeyframe) y1 = br.bottom() - (br.height() /2);
+ else y1 = br.bottom() - (i.value() - m_keyframeOffset) * maxh;
if (qAbs(pos.x() - x1) < maxOffset && qAbs(pos.y() - y1) < 10) {
setToolTip('[' + QString::number((GenTime(i.key(), m_fps) - cropStart()).seconds(), 'f', 2) + i18n("seconds") + ", " + QString::number(i.value(), 'f', 1) + ']');
return i.key();
diff --git a/src/timeline/abstractclipitem.h b/src/timeline/abstractclipitem.h
index e65d4b0..b5d4ed9 100644
--- a/src/timeline/abstractclipitem.h
+++ b/src/timeline/abstractclipitem.h
@@ -40,6 +40,14 @@ class AbstractClipItem : public QObject, public QGraphicsRectItem
Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity)
public:
+
+ enum KEYFRAMETYPE {
+ NoKeyframe = 0,
+ SimpleKeyframe,
+ NormalKeyframe,
+ GeometryKeyframe
+ };
+
AbstractClipItem(const ItemInfo &info, const QRectF& rect, double fps);
virtual ~ AbstractClipItem();
void updateSelectedKeyFrame();
@@ -107,6 +115,7 @@ protected:
GenTime m_cropDuration;
GenTime m_startPos;*/
GenTime m_maxDuration;
+ KEYFRAMETYPE m_keyframeType;
QMap <int, int> m_keyframes;
/** @brief Stretch factor so that keyframes display on the full clip height. */
double m_keyframeFactor;
@@ -121,11 +130,8 @@ protected:
bool m_isMainSelectedClip;
/** @brief Draw the keyframes of a clip
* @param painter The painter device for the clip
- * @param limitedKeyFrames The keyframes can be of type "keyframe" or "simplekeyframe". In the
- * "simplekeyframe" type, the effect always starts on clip start and ends on clip end. With the
- * "keyframe" type, the effect starts on the first keyframe and ends on the last keyframe
*/
- void drawKeyFrames(QPainter *painter, const QTransform &transformation, bool limitedKeyFrames);
+ void drawKeyFrames(QPainter *painter, const QTransform &transformation);
int mouseOverKeyFrames(QPointF pos, double maxOffset);
void mousePressEvent(QGraphicsSceneMouseEvent * event);
diff --git a/src/timeline/clipitem.cpp b/src/timeline/clipitem.cpp
index f9422cc..4f75fed 100644
--- a/src/timeline/clipitem.cpp
+++ b/src/timeline/clipitem.cpp
@@ -58,8 +58,7 @@ ClipItem::ClipItem(ProjectClip *clip, const ItemInfo& info, double fps, double s
//m_hover(false),
m_speed(speed),
m_strobe(strobe),
- m_framePixelWidth(0),
- m_limitedKeyFrames(false)
+ m_framePixelWidth(0)
{
setZValue(2);
m_effectList = EffectsList(true);
@@ -349,30 +348,14 @@ void ClipItem::setSelectedEffect(const int ix)
QLocale locale;
locale.setNumberOptions(QLocale::OmitGroupSeparator);
QDomElement effect = effectAtIndex(m_selectedEffect);
+ m_keyframeType = NoKeyframe;
if (!effect.isNull() && effect.attribute("disable") != "1") {
QDomNodeList params = effect.elementsByTagName("parameter");
for (int i = 0; i < params.count(); ++i) {
QDomElement e = params.item(i).toElement();
- if (!e.isNull() && (e.attribute("type") == "keyframe" || e.attribute("type") == "simplekeyframe") && (!e.hasAttribute("intimeline") || e.attribute("intimeline") == "1")) {
- m_keyframes.clear();
- m_limitedKeyFrames = e.attribute("type") == "keyframe";
+ if (e.isNull()) continue;
+ if (parseKeyframes(locale, e)) {
m_visibleParam = i;
- double max = locale.toDouble(e.attribute("max"));
- double min = locale.toDouble(e.attribute("min"));
- m_keyframeFactor = 100.0 / (max - min);
- m_keyframeOffset = min;
- m_keyframeDefault = locale.toDouble(e.attribute("default"));
- m_selectedKeyframe = 0;
-
- // parse keyframes
- const QStringList keyframes = e.attribute("keyframes").split(';', QString::SkipEmptyParts);
- foreach(const QString &str, keyframes) {
- int pos = str.section('=', 0, 0).toInt();
- double val = locale.toDouble(str.section('=', 1, 1));
- m_keyframes[pos] = val;
- }
- if (m_keyframes.find(m_editedKeyframe) == m_keyframes.end())
- m_editedKeyframe = -1;
update();
return;
}
@@ -641,13 +624,13 @@ void ClipItem::setClipName(const QString &name)
void ClipItem::flashClip()
{
if (m_timeLine == 0) {
- m_timeLine = new QTimeLine(750, this);
+ m_timeLine = new QTimeLine(500, this);
m_timeLine->setUpdateInterval(80);
m_timeLine->setCurveShape(QTimeLine::EaseInOutCurve);
m_timeLine->setFrameRange(0, 100);
connect(m_timeLine, SIGNAL(valueChanged(qreal)), this, SLOT(animate(qreal)));
}
- //m_timeLine->start();
+ m_timeLine->start();
}
void ClipItem::animate(qreal /*value*/)
@@ -938,7 +921,7 @@ void ClipItem::paint(QPainter *painter,
painter->setPen(QPen(Qt::lightGray));
// draw effect or transition keyframes
- drawKeyFrames(painter, transformation, m_limitedKeyFrames);
+ drawKeyFrames(painter, transformation);
}
// draw clip border
@@ -1373,7 +1356,7 @@ bool ClipItem::moveEffect(QDomElement effect, int ix)
return true;
}
-EffectsParameterList ClipItem::addEffect(ProfileInfo info, QDomElement effect, bool /*animate*/)
+EffectsParameterList ClipItem::addEffect(ProfileInfo info, QDomElement effect, bool animate)
{
bool needRepaint = false;
QLocale locale;
@@ -1514,14 +1497,16 @@ EffectsParameterList ClipItem::addEffect(ProfileInfo info, QDomElement effect, b
if (m_selectedEffect == -1) {
setSelectedEffect(1);
} else if (m_selectedEffect == ix - 1) setSelectedEffect(m_selectedEffect);
- if (needRepaint) update(boundingRect());
- /*if (animate) {
- flashClip();
- } */
- else { /*if (!needRepaint) */
- QRectF r = boundingRect();
- r.setHeight(20);
- update(r);
+ if (needRepaint) {
+ update(boundingRect());
+ }
+ else {
+ if (animate) flashClip();
+ else {
+ QRectF r = boundingRect();
+ r.setHeight(20);
+ update(r);
+ }
}
return parameters;
}
@@ -1557,7 +1542,7 @@ void ClipItem::deleteEffect(int ix)
r.setHeight(20);
update(r);
}
- //if (!m_effectList.isEmpty()) flashClip();
+ if (!m_effectList.isEmpty()) flashClip();
}
double ClipItem::speed() const
@@ -1757,7 +1742,8 @@ void ClipItem::movedKeyframe(QDomElement effect, int oldpos, int newpos, double
int end = (cropStart() + cropDuration()).frames(m_fps) - 1;
for (int i = 0; i < params.count(); ++i) {
QDomElement e = params.item(i).toElement();
- if (!e.isNull() && (e.attribute("type") == "keyframe" || e.attribute("type") == "simplekeyframe")) {
+ if (e.isNull()) continue;
+ if ((e.attribute("type") == "keyframe" || e.attribute("type") == "simplekeyframe")) {
QString kfr = e.attribute("keyframes");
const QStringList keyframes = kfr.split(';', QString::SkipEmptyParts);
QStringList newkfr;
@@ -1775,6 +1761,21 @@ void ClipItem::movedKeyframe(QDomElement effect, int oldpos, int newpos, double
}
e.setAttribute("keyframes", newkfr.join(";"));
}
+ else if (e.attribute("type") == "geometry") {
+ QString kfr = e.attribute("value");
+ const QStringList keyframes = kfr.split(';', QString::SkipEmptyParts);
+ QStringList newkfr;
+ foreach(const QString &str, keyframes) {
+ if (str.section('=', 0, 0).toInt() != oldpos) {
+ newkfr.append(str);
+ } else if (newpos != -1) {
+ newpos = qMax(newpos, start);
+ newpos = qMin(newpos, end);
+ newkfr.append(QString::number(newpos) + '=' + str.section('=', 1, 1));
+ }
+ }
+ e.setAttribute("value", newkfr.join(";"));
+ }
}
updateKeyframes(effect);
@@ -1789,18 +1790,44 @@ void ClipItem::updateKeyframes(QDomElement effect)
// parse keyframes
QDomNodeList params = effect.elementsByTagName("parameter");
QDomElement e = params.item(m_visibleParam).toElement();
+ if (e.isNull()) return;
if (e.attribute("intimeline") != "1") {
setSelectedEffect(m_selectedEffect);
return;
}
- m_limitedKeyFrames = e.attribute("type") == "keyframe";
- const QStringList keyframes = e.attribute("keyframes").split(';', QString::SkipEmptyParts);
- foreach(const QString &str, keyframes) {
- int pos = str.section('=', 0, 0).toInt();
- double val = locale.toDouble(str.section('=', 1, 1));
- m_keyframes[pos] = val;
+ parseKeyframes(locale, e);
+}
+
+bool ClipItem::parseKeyframes(const QLocale locale, QDomElement e)
+{
+ QString type = e.attribute("type");
+ if (type == "keyframe") m_keyframeType = NormalKeyframe;
+ else if (type == "simplekeyframe") m_keyframeType = SimpleKeyframe;
+ else if (type == "geometry") m_keyframeType = GeometryKeyframe;
+ if (m_keyframeType != NoKeyframe && (!e.hasAttribute("intimeline") || e.attribute("intimeline") == "1")) {
+ m_keyframes.clear();
+ double max = locale.toDouble(e.attribute("max"));
+ double min = locale.toDouble(e.attribute("min"));
+ m_keyframeFactor = 100.0 / (max - min);
+ m_keyframeOffset = min;
+ m_keyframeDefault = locale.toDouble(e.attribute("default"));
+ m_selectedKeyframe = 0;
+
+ // parse keyframes
+ QStringList keyframes;
+ if (m_keyframeType == GeometryKeyframe) keyframes = e.attribute("value").split(';', QString::SkipEmptyParts);
+ else keyframes = e.attribute("keyframes").split(';', QString::SkipEmptyParts);
+ foreach(const QString &str, keyframes) {
+ int pos = str.section('=', 0, 0).toInt();
+ double val = m_keyframeType == GeometryKeyframe ? 0 : locale.toDouble(str.section('=', 1, 1));
+ m_keyframes[pos] = val;
+ }
+ if (m_keyframes.find(m_editedKeyframe) == m_keyframes.end()) {
+ m_editedKeyframe = -1;
+ }
+ return true;
}
- if (!m_keyframes.contains(m_selectedKeyframe)) m_selectedKeyframe = -1;
+ return false;
}
/*
diff --git a/src/timeline/clipitem.h b/src/timeline/clipitem.h
index 047db1f..96856f7 100644
--- a/src/timeline/clipitem.h
+++ b/src/timeline/clipitem.h
@@ -241,9 +241,7 @@ private:
QPixmap m_videoPix;
QPixmap m_audioPix;
- /** @brief Keyframes type can be "keyframe" or "simplekeyframe" which have to be painted differently.
- * True if keyframe type is "keyframe" */
- bool m_limitedKeyFrames;
+ bool parseKeyframes(const QLocale locale, QDomElement e);
private slots:
void slotGetStartThumb();
diff --git a/src/ui/geometrywidget_ui.ui b/src/ui/geometrywidget_ui.ui
index d412e48..63ffe6e 100644
--- a/src/ui/geometrywidget_ui.ui
+++ b/src/ui/geometrywidget_ui.ui
@@ -11,7 +11,16 @@
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_3">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
@@ -20,7 +29,16 @@
<item row="0" column="0">
<widget class="QWidget" name="widgetTimeWrapper" native="true">
<layout class="QGridLayout" name="gridLayout_4">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item row="1" column="3">
@@ -87,18 +105,6 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>20</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>20</height>
- </size>
- </property>
</widget>
</item>
</layout>
@@ -113,7 +119,16 @@
<enum>QFrame::Plain</enum>
</property>
<layout class="QGridLayout" name="gridLayout">
- <property name="margin">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0" colspan="2">