]> git.sesse.net Git - kdenlive/commitdiff
Improve keyframe editor, fix random keyframe sometimes inserted
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Tue, 17 Nov 2009 16:48:26 +0000 (16:48 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Tue, 17 Nov 2009 16:48:26 +0000 (16:48 +0000)
svn path=/trunk/kdenlive/; revision=4130

src/abstractclipitem.cpp
src/clipitem.cpp
src/effectstackedit.cpp
src/keyframeedit.cpp
src/keyframeedit.h
src/trackview.cpp
src/widgets/keyframeeditor_ui.ui

index 47905faad8b9e4728944d093d3d11cb797a5dc38..6584428fb56d3526ae3f44886226740092981904 100644 (file)
@@ -149,7 +149,6 @@ void AbstractClipItem::resizeStart(int posx)
     moveBy(durationDiff.frames(m_fps), 0);
 
     if (m_info.startPos != GenTime(posx, m_fps)) {
-        kDebug() << "__ RESIZE START OFFSET: ";
         //kDebug()<<"//////  WARNING, DIFF IN XPOS: "<<pos().x()<<" == "<<m_startPos.frames(m_fps);
         GenTime diff = m_info.startPos - GenTime((int) posx, m_fps);
 
@@ -241,7 +240,7 @@ GenTime AbstractClipItem::maxDuration() const
 
 void AbstractClipItem::drawKeyFrames(QPainter *painter, QRectF /*exposedRect*/)
 {
-    if (m_keyframes.count() < 2) return;
+    if (m_keyframes.count() < 1) return;
     QRectF br = rect();
     double maxw = br.width() / cropDuration().frames(m_fps);
     double maxh = br.height() / 100.0 * m_keyframeFactor;
@@ -275,9 +274,16 @@ void AbstractClipItem::drawKeyFrames(QPainter *painter, QRectF /*exposedRect*/)
         if (i.key() == m_selectedKeyframe) color = QColor(Qt::red);
         else color = QColor(Qt::blue);
         ++i;
-        if (i == m_keyframes.constEnd()) break;
-        x2 = br.x() + maxw * (i.key() - cropStart().frames(m_fps));
-        y2 = br.bottom() - i.value() * maxh;
+        if (i == m_keyframes.constEnd() && m_keyframes.count() != 1) {
+            break;
+        }
+        if (m_keyframes.count() == 1) {
+            x2 = br.right();
+            y2 = y1;
+        } else {
+            x2 = br.x() + maxw * (i.key() - cropStart().frames(m_fps));
+            y2 = br.bottom() - i.value() * maxh;
+        }
         QLineF l(x1, y1, x2, y2);
         l2 = painter->matrix().map(l);
         painter->drawLine(l2);
@@ -299,7 +305,7 @@ int AbstractClipItem::mouseOverKeyFrames(QPointF pos, double maxOffset)
     const QRectF br = sceneBoundingRect();
     double maxw = br.width() / cropDuration().frames(m_fps);
     double maxh = br.height() / 100.0 * m_keyframeFactor;
-    if (m_keyframes.count() > 1) {
+    if (m_keyframes.count() > 0) {
         QMap<int, int>::const_iterator i = m_keyframes.constBegin();
         double x1;
         double y1;
@@ -335,7 +341,7 @@ int AbstractClipItem::selectedKeyFramePos() const
 
 double AbstractClipItem::selectedKeyFrameValue() const
 {
-    return m_keyframes[m_editedKeyframe];
+    return m_keyframes.value(m_editedKeyframe);
 }
 
 void AbstractClipItem::updateKeyFramePos(const GenTime pos, const double value)
@@ -366,6 +372,7 @@ void AbstractClipItem::updateKeyFramePos(const GenTime pos, const double value)
     if (m_selectedKeyframe != newpos) m_keyframes.remove(m_selectedKeyframe);
     m_keyframes[newpos] = (int) newval;
     m_selectedKeyframe = newpos;
+
     update();
 }
 
index 504d57aa120a7b8fb545a192fdae0343d902efb9..7ef69ea4a7bf01e77fbb05da3bab9e9086b61b18 100644 (file)
@@ -324,6 +324,8 @@ void ClipItem::setKeyframes(const int ix, const QString keyframes)
                 double min = e.attribute("min").toDouble();
                 m_keyframeFactor = 100.0 / (max - min);
                 m_keyframeDefault = e.attribute("default").toDouble();
+                m_selectedKeyframe = 0;
+                m_editedKeyframe = -1;
                 // parse keyframes
                 const QStringList keyframes = e.attribute("keyframes").split(';', QString::SkipEmptyParts);
                 foreach(const QString &str, keyframes) {
@@ -355,6 +357,8 @@ void ClipItem::setSelectedEffect(const int ix)
                     double min = e.attribute("min").toDouble();
                     m_keyframeFactor = 100.0 / (max - min);
                     m_keyframeDefault = e.attribute("default").toDouble();
+                    m_selectedKeyframe = 0;
+                    m_editedKeyframe = -1;
                     // parse keyframes
                     const QStringList keyframes = e.attribute("keyframes").split(';', QString::SkipEmptyParts);
                     foreach(const QString &str, keyframes) {
@@ -400,7 +404,7 @@ void ClipItem::updateKeyframeEffect()
         QDomElement e = params.item(i).toElement();
         if (!e.isNull() && (e.attribute("type") == "keyframe" || e.attribute("type") == "simplekeyframe")) {
             QString keyframes;
-            if (m_keyframes.count() > 1) {
+            if (m_keyframes.count() > 0) {
                 QMap<int, int>::const_iterator i = m_keyframes.constBegin();
                 while (i != m_keyframes.constEnd()) {
                     keyframes.append(QString::number(i.key()) + ':' + QString::number(i.value()) + ';');
@@ -856,20 +860,20 @@ OPERATIONTYPE ClipItem::operationMode(QPointF pos)
 
     if (qAbs((int)(pos.x() - (rect.x() + m_startFade))) < maximumOffset  && qAbs((int)(pos.y() - rect.y())) < 6) {
         if (m_startFade == 0) setToolTip(i18n("Add audio fade"));
-       // xgettext:no-c-format
+        // xgettext:no-c-format
         else setToolTip(i18n("Audio fade duration: %1s", GenTime(m_startFade, m_fps).seconds()));
         return FADEIN;
     } else if (pos.x() - rect.x() < maximumOffset && (rect.bottom() - pos.y() > addtransitionOffset)) {
-       // xgettext:no-c-format
+        // xgettext:no-c-format
         setToolTip(i18n("Crop from start: %1s", cropStart().seconds()));
         return RESIZESTART;
     } else if (qAbs((int)(pos.x() - (rect.x() + rect.width() - m_endFade))) < maximumOffset && qAbs((int)(pos.y() - rect.y())) < 6) {
         if (m_endFade == 0) setToolTip(i18n("Add audio fade"));
-       // xgettext:no-c-format
+        // xgettext:no-c-format
         else setToolTip(i18n("Audio fade duration: %1s", GenTime(m_endFade, m_fps).seconds()));
         return FADEOUT;
     } else if ((rect.right() - pos.x() < maximumOffset) && (rect.bottom() - pos.y() > addtransitionOffset)) {
-       // xgettext:no-c-format
+        // xgettext:no-c-format
         setToolTip(i18n("Clip duration: %1s", cropDuration().seconds()));
         return RESIZEEND;
     } else if ((pos.x() - rect.x() < 16 / scale) && (rect.bottom() - pos.y() <= addtransitionOffset)) {
@@ -1312,22 +1316,21 @@ EffectsParameterList ClipItem::addEffect(const QDomElement effect, bool /*animat
     for (int i = 0; i < params.count(); i++) {
         QDomElement e = params.item(i).toElement();
         if (!e.isNull()) {
-           if (e.attribute("type") == "simplekeyframe") {
-               QStringList values = e.attribute("keyframes").split(";", QString::SkipEmptyParts);
-               double factor = e.attribute("factor", "1").toDouble();
-               if (factor != 1) {
-                   for (int j = 0; j < values.count(); j++) {
-                       QString pos = values.at(j).section(":", 0, 0);
-                       double val = values.at(j).section(":", 1, 1).toDouble() / factor;
-                       values[j] = pos + "=" + QString::number(val);
-                   }
-               }
+            if (e.attribute("type") == "simplekeyframe") {
+                QStringList values = e.attribute("keyframes").split(";", QString::SkipEmptyParts);
+                double factor = e.attribute("factor", "1").toDouble();
+                if (factor != 1) {
+                    for (int j = 0; j < values.count(); j++) {
+                        QString pos = values.at(j).section(":", 0, 0);
+                        double val = values.at(j).section(":", 1, 1).toDouble() / factor;
+                        values[j] = pos + "=" + QString::number(val);
+                    }
+                }
                 parameters.addParam(e.attribute("name"), values.join(";"));
                 /*parameters.addParam("max", e.attribute("max"));
                 parameters.addParam("min", e.attribute("min"));
                 parameters.addParam("factor", );*/
-            }
-            else if (e.attribute("type") == "keyframe") {
+            } else if (e.attribute("type") == "keyframe") {
                 parameters.addParam("keyframes", e.attribute("keyframes"));
                 parameters.addParam("max", e.attribute("max"));
                 parameters.addParam("min", e.attribute("min"));
@@ -1422,24 +1425,23 @@ EffectsParameterList ClipItem::getEffectArgs(const QDomElement effect)
     for (int i = 0; i < params.count(); i++) {
         QDomElement e = params.item(i).toElement();
         //kDebug() << "/ / / /SENDING EFFECT PARAM: " << e.attribute("type") << ", NAME_ " << e.attribute("tag");
-       if (e.attribute("type") == "simplekeyframe") {
+        if (e.attribute("type") == "simplekeyframe") {
             kDebug() << "/ / / /SENDING KEYFR EFFECT TYPE";
-           QStringList values = e.attribute("keyframes").split(";", QString::SkipEmptyParts);
-           double factor = e.attribute("factor", "1").toDouble();
-           if (factor != 1) {
-               for (int j = 0; j < values.count(); j++) {
-                   QString pos = values.at(j).section(":", 0, 0);
-                   double val = values.at(j).section(":", 1, 1).toDouble() / factor;
-                   values[j] = pos + "=" + QString::number(val);
-               }
-           }
+            QStringList values = e.attribute("keyframes").split(";", QString::SkipEmptyParts);
+            double factor = e.attribute("factor", "1").toDouble();
+            if (factor != 1) {
+                for (int j = 0; j < values.count(); j++) {
+                    QString pos = values.at(j).section(":", 0, 0);
+                    double val = values.at(j).section(":", 1, 1).toDouble() / factor;
+                    values[j] = pos + "=" + QString::number(val);
+                }
+            }
             parameters.addParam(e.attribute("name"), values.join(";"));
             /*parameters.addParam(e.attribute("name"), e.attribute("keyframes").replace(":", "="));
             parameters.addParam("max", e.attribute("max"));
             parameters.addParam("min", e.attribute("min"));
             parameters.addParam("factor", e.attribute("factor", "1"));*/
-        }
-        else if (e.attribute("type") == "keyframe") {
+        } else if (e.attribute("type") == "keyframe") {
             kDebug() << "/ / / /SENDING KEYFR EFFECT TYPE";
             parameters.addParam("keyframes", e.attribute("keyframes"));
             parameters.addParam("max", e.attribute("max"));
index add62549ad4efb4a9b70a38b24c7dc533a3886dc..e2db15e93322578f3150a0a9a6f25adb887a2f27 100644 (file)
@@ -234,7 +234,7 @@ void EffectStackEdit::transferParamDesc(const QDomElement d, int in, int out)
         } else if (type == "keyframe" || type == "simplekeyframe") {
             // keyframe editor widget
             kDebug() << "min: " << m_in << ", MAX: " << m_out;
-            KeyframeEdit *geo = new KeyframeEdit(pa, m_out - m_in - 1, pa.attribute("min").toInt(), pa.attribute("max").toInt(), m_timecode);
+            KeyframeEdit *geo = new KeyframeEdit(pa, m_out - m_in - 1, pa.attribute("min").toInt(), pa.attribute("max").toInt(), m_timecode, paramName);
             //geo->setupParam(100, pa.attribute("min").toInt(), pa.attribute("max").toInt(), pa.attribute("keyframes"));
             //connect(geo, SIGNAL(seekToPos(int)), this, SLOT(slotSeekToPos(int)));
             //geo->setupParam(pa, minFrame, maxFrame);
index 847caaab32f7578f227604d9fc3c2da9c4dbf511..be033ffa6a500a8856be9a89f039b60378771f64 100644 (file)
@@ -24,7 +24,7 @@
 #include <QHeaderView>
 
 
-KeyframeEdit::KeyframeEdit(QDomElement e, int maxFrame, int minVal, int maxVal, Timecode tc, QWidget* parent) :
+KeyframeEdit::KeyframeEdit(QDomElement e, int maxFrame, int minVal, int maxVal, Timecode tc, const QString paramName, QWidget* parent) :
         QWidget(parent),
         m_param(e),
         m_max(maxFrame),
@@ -35,18 +35,23 @@ KeyframeEdit::KeyframeEdit(QDomElement e, int maxFrame, int minVal, int maxVal,
 {
     setupUi(this);
     keyframe_list->setFont(KGlobalSettings::generalFont());
-    keyframe_list->setHeaderLabels(QStringList() << i18n("Position") << i18n("Value"));
+    keyframe_list->setHeaderLabels(QStringList() << i18n("Position") << (paramName.isEmpty() ? i18n("Value") : paramName));
     //setResizeMode(1, QHeaderView::Interactive);
-    button_add->setIcon(KIcon("document-new"));
-    button_delete->setIcon(KIcon("edit-delete"));
+    button_add->setIcon(KIcon("list-add"));
+    button_add->setToolTip(i18n("Add keyframe"));
+    button_delete->setIcon(KIcon("list-remove"));
+    button_delete->setToolTip(i18n("Delete keyframe"));
     connect(keyframe_list, SIGNAL(itemSelectionChanged()/*itemClicked(QTreeWidgetItem *, int)*/), this, SLOT(slotAdjustKeyframeInfo()));
+    keyframe_val->setRange(m_minVal, m_maxVal);
     setupParam();
+
     keyframe_list->header()->resizeSections(QHeaderView::ResizeToContents);
     connect(button_delete, SIGNAL(clicked()), this, SLOT(slotDeleteKeyframe()));
     connect(button_add, SIGNAL(clicked()), this, SLOT(slotAddKeyframe()));
     connect(keyframe_list, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(slotGenerateParams(QTreeWidgetItem *, int)));
     connect(keyframe_list, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(slotSaveCurrentParam(QTreeWidgetItem *, int)));
-    connect(keyframe_pos, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustKeyframeValue(int)));
+    connect(keyframe_pos, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustKeyframePos(int)));
+    connect(keyframe_val, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustKeyframeValue(int)));
     keyframe_pos->setPageStep(1);
     m_delegate = new KeyItemDelegate(minVal, maxVal);
     keyframe_list->setItemDelegate(m_delegate);
@@ -73,18 +78,18 @@ void KeyframeEdit::setupParam(QDomElement e)
     QTreeWidgetItem *first = keyframe_list->topLevelItem(0);
     if (first) keyframe_list->setCurrentItem(first);
     slotAdjustKeyframeInfo();
-    button_delete->setEnabled(keyframe_list->topLevelItemCount() > 2);
+    button_delete->setEnabled(keyframe_list->topLevelItemCount() > 1);
 }
 
 void KeyframeEdit::slotDeleteKeyframe()
 {
-    if (keyframe_list->topLevelItemCount() < 3) return;
+    if (keyframe_list->topLevelItemCount() < 2) return;
     QTreeWidgetItem *item = keyframe_list->currentItem();
     if (item) {
         delete item;
         slotGenerateParams();
     }
-    button_delete->setEnabled(keyframe_list->topLevelItemCount() > 2);
+    button_delete->setEnabled(keyframe_list->topLevelItemCount() > 1);
 }
 
 void KeyframeEdit::slotAddKeyframe()
@@ -112,7 +117,7 @@ void KeyframeEdit::slotAddKeyframe()
     keyframe_list->setCurrentItem(newItem);
     slotAdjustKeyframeInfo();
     keyframe_list->blockSignals(false);
-    button_delete->setEnabled(keyframe_list->topLevelItemCount() > 2);
+    button_delete->setEnabled(keyframe_list->topLevelItemCount() > 1);
     slotGenerateParams();
 }
 
@@ -166,14 +171,23 @@ void KeyframeEdit::slotAdjustKeyframeInfo()
     keyframe_pos->setRange(min, max);
     keyframe_pos->setValue(m_timecode.getFrameCount(item->text(0)));
     keyframe_pos->blockSignals(false);
+    keyframe_val->blockSignals(true);
+    keyframe_val->setValue(item->text(1).toInt());
+    keyframe_val->blockSignals(false);
 }
 
-void KeyframeEdit::slotAdjustKeyframeValue(int value)
+void KeyframeEdit::slotAdjustKeyframePos(int value)
 {
     QTreeWidgetItem *item = keyframe_list->currentItem();
     item->setText(0, m_timecode.getTimecodeFromFrames(value));
 }
 
+void KeyframeEdit::slotAdjustKeyframeValue(int value)
+{
+    QTreeWidgetItem *item = keyframe_list->currentItem();
+    item->setText(1, QString::number(value));
+}
+
 void KeyframeEdit::slotSaveCurrentParam(QTreeWidgetItem *item, int column)
 {
     if (item && column == 0) m_previousPos = m_timecode.getFrameCount(item->text(0));
index 8de47f02f2666a9253f0383a5e459cd7fb56ca0d..0aa620d26a9427f961870fae895fd7328d5d732e 100644 (file)
@@ -75,7 +75,7 @@ class KeyframeEdit : public QWidget, public Ui::KeyframeEditor_UI
 {
     Q_OBJECT
 public:
-    explicit KeyframeEdit(QDomElement e, int maxFrame, int minVal, int maxVal, Timecode tc, QWidget* parent = 0);
+    explicit KeyframeEdit(QDomElement e, int maxFrame, int minVal, int maxVal, Timecode tc, const QString paramName = QString(), QWidget* parent = 0);
     virtual ~KeyframeEdit();
     void setupParam(QDomElement e = QDomElement());
 
@@ -96,6 +96,7 @@ private slots:
     void slotAddKeyframe();
     void slotGenerateParams(QTreeWidgetItem *item = NULL, int column = -1);
     void slotAdjustKeyframeInfo();
+    void slotAdjustKeyframePos(int value);
     void slotAdjustKeyframeValue(int value);
     void slotSaveCurrentParam(QTreeWidgetItem *item, int column);
 
index 16e0da314683bb46a31b69d0b36313a530b22381..b6009c1a9dd4564baa1225c3981bad80f9121616 100644 (file)
@@ -689,7 +689,7 @@ int TrackView::slotAddProjectTrack(int ix, QDomElement xml, bool locked)
                             QDomElement currenteffect = clipeffect.cloneNode().toElement();
                             currenteffect.setAttribute("kdenlive_ix", effectindex);
                             QDomNodeList clipeffectparams = currenteffect.childNodes();
-                           
+
                             if (MainWindow::videoEffects.hasKeyFrames(currenteffect)) {
                                 //kDebug() << " * * * * * * * * * * ** CLIP EFF WITH KFR FND  * * * * * * * * * * *";
                                 // effect is key-framable, read all effects to retrieve keyframes
@@ -792,16 +792,15 @@ int TrackView::slotAddProjectTrack(int ix, QDomElement xml, bool locked)
                                             if (factor.startsWith('%')) {
                                                 fact = ProfilesDialog::getStringEval(m_doc->mltProfile(), factor);
                                             } else fact = factor.toDouble();
-                                           if (e.attribute("type") == "simplekeyframe") {
-                                               QStringList kfrs = paramvalue.split(";");
-                                               for (int l = 0; l < kfrs.count(); l++) {
-                                                   QString fr = kfrs.at(l).section("=", 0, 0);
-                                                   double val = kfrs.at(l).section("=", 1, 1).toDouble();
-                                                   kfrs[l] = fr + ":" + QString::number((int) (val * fact));
-                                               }
-                                               e.setAttribute("keyframes", kfrs.join(";"));
-                                           }
-                                            else e.setAttribute("value", paramvalue.toDouble() * fact);
+                                            if (e.attribute("type") == "simplekeyframe") {
+                                                QStringList kfrs = paramvalue.split(";");
+                                                for (int l = 0; l < kfrs.count(); l++) {
+                                                    QString fr = kfrs.at(l).section("=", 0, 0);
+                                                    double val = kfrs.at(l).section("=", 1, 1).toDouble();
+                                                    kfrs[l] = fr + ":" + QString::number((int)(val * fact));
+                                                }
+                                                e.setAttribute("keyframes", kfrs.join(";"));
+                                            } else e.setAttribute("value", paramvalue.toDouble() * fact);
                                         } else e.setAttribute("value", paramvalue);
                                         break;
                                     }
index d7023a63597293fe1e5d3a043e54c7b780698a13..082f86e6a02f56759915816d753675c9a8350a9a 100644 (file)
@@ -6,18 +6,15 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>157</width>
-    <height>103</height>
+    <width>213</width>
+    <height>177</height>
    </rect>
   </property>
   <layout class="QGridLayout" name="gridLayout">
    <property name="margin">
     <number>0</number>
    </property>
-   <property name="spacing">
-    <number>0</number>
-   </property>
-   <item row="0" column="0" colspan="4">
+   <item row="0" column="0" colspan="2">
     <widget class="QTreeWidget" name="keyframe_list">
      <property name="alternatingRowColors">
       <bool>true</bool>
     </widget>
    </item>
    <item row="1" column="0">
-    <widget class="QToolButton" name="button_add">
-     <property name="text">
-      <string>A</string>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QToolButton" name="button_add">
+       <property name="text">
+        <string>A</string>
+       </property>
+       <property name="arrowType">
+        <enum>Qt::NoArrow</enum>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QToolButton" name="button_delete">
+       <property name="text">
+        <string>D</string>
+       </property>
+       <property name="arrowType">
+        <enum>Qt::NoArrow</enum>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="1" column="1">
+    <spacer name="horizontalSpacer">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
      </property>
-     <property name="arrowType">
-      <enum>Qt::NoArrow</enum>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>40</width>
+       <height>20</height>
+      </size>
      </property>
-    </widget>
+    </spacer>
    </item>
-   <item row="1" column="1">
-    <widget class="QToolButton" name="button_delete">
+   <item row="2" column="0">
+    <widget class="QLabel" name="label">
      <property name="text">
-      <string>D</string>
+      <string>Position</string>
      </property>
-     <property name="arrowType">
-      <enum>Qt::NoArrow</enum>
+    </widget>
+   </item>
+   <item row="2" column="1">
+    <widget class="QSlider" name="keyframe_pos">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
      </property>
     </widget>
    </item>
-   <item row="1" column="2">
-    <widget class="QLabel" name="label">
+   <item row="3" column="0">
+    <widget class="QLabel" name="label_2">
      <property name="text">
-      <string>Pos</string>
+      <string>Value</string>
      </property>
     </widget>
    </item>
-   <item row="1" column="3">
-    <widget class="QSlider" name="keyframe_pos">
+   <item row="3" column="1">
+    <widget class="QSlider" name="keyframe_val">
      <property name="orientation">
       <enum>Qt::Horizontal</enum>
      </property>