]> git.sesse.net Git - kdenlive/commitdiff
Finished effect keyframe editor
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Tue, 23 Jun 2009 15:34:28 +0000 (15:34 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Tue, 23 Jun 2009 15:34:28 +0000 (15:34 +0000)
svn path=/trunk/kdenlive/; revision=3623

src/customtrackview.cpp
src/effectstackedit.cpp
src/keyframeedit.cpp
src/keyframeedit.h
src/widgets/keyframeeditor_ui.ui

index 04f3594d68ccf888567a68f71b69dd0f74d5d53f..397eb4bddf9c6cefd1bc5c0edec36cb3509ebdac 100644 (file)
@@ -1017,6 +1017,7 @@ void CustomTrackView::mouseDoubleClickEvent(QMouseEvent *event)
                 EditKeyFrameCommand *command = new EditKeyFrameCommand(this, item->track(), item->startPos(), item->selectedEffectIndex(), previous, next, false);
                 m_commandStack->push(command);
                 updateEffect(m_document->tracksCount() - item->track(), item->startPos(), item->selectedEffect(), item->selectedEffectIndex());
+                emit clipItemSelected(item, item->selectedEffectIndex());
             }
 
         } else  {
@@ -1030,6 +1031,7 @@ void CustomTrackView::mouseDoubleClickEvent(QMouseEvent *event)
             EditKeyFrameCommand *command = new EditKeyFrameCommand(this, m_dragItem->track(), m_dragItem->startPos(), item->selectedEffectIndex(), previous, next, false);
             m_commandStack->push(command);
             updateEffect(m_document->tracksCount() - item->track(), item->startPos(), item->selectedEffect(), item->selectedEffectIndex());
+            emit clipItemSelected(item, item->selectedEffectIndex());
         }
     } else if (m_dragItem && !m_dragItem->isItemLocked()) {
         ClipDurationDialog d(m_dragItem, m_document->timecode(), this);
@@ -2719,6 +2721,7 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event)
         EditKeyFrameCommand *command = new EditKeyFrameCommand(this, item->track(), item->startPos(), item->selectedEffectIndex(), previous, next, false);
         m_commandStack->push(command);
         updateEffect(m_document->tracksCount() - item->track(), item->startPos(), item->selectedEffect(), item->selectedEffectIndex());
+        emit clipItemSelected(item, item->selectedEffectIndex());
     }
     if (m_dragItem && m_dragItem->type() == TRANSITIONWIDGET && m_dragItem->isSelected()) {
         // A transition is selected
index 9295d82510dc9c7ee9a6ab3b9678210cb33a7429..6edc614506795811345b171cbc3c1ba1f2be491d 100644 (file)
@@ -238,9 +238,10 @@ void EffectStackEdit::transferParamDesc(const QDomElement& d, int in, int out)
             m_items.append(geo);
         } else if (type == "keyframe") {
             // keyframe editor widget
-            KeyframeEdit *geo = new KeyframeEdit(m_timecode);
+            kDebug() << "min: " << m_in << ", MAX: " << m_out;
+            KeyframeEdit *geo = new KeyframeEdit(pa, m_out - m_in, m_timecode);
             connect(geo, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters()));
-            geo->setupParam(100, pa.attribute("min").toInt(), pa.attribute("max").toInt(), pa.attribute("keyframes"));
+            //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);
             m_vbox->addWidget(geo);
index 26eaf86cf648bc38d89d8fdadfa45eb0a025557d..b7523579cf996da7f1fb1f976af8ee32516de713 100644 (file)
 #include <KDebug>
 
 
-KeyframeEdit::KeyframeEdit(Timecode tc, QWidget* parent) :
+KeyframeEdit::KeyframeEdit(QDomElement e, int max, Timecode tc, QWidget* parent) :
         QWidget(parent),
-        m_timecode(tc)
+        m_param(e),
+        m_max(max),
+        m_timecode(tc),
+        m_previousPos(0)
 {
     m_ui.setupUi(this);
     m_ui.keyframe_list->setHeaderLabels(QStringList() << i18n("Position") << i18n("Value"));
+    //setResizeMode(1, QHeaderView::Interactive);
     m_ui.button_add->setIcon(KIcon("document-new"));
     m_ui.button_delete->setIcon(KIcon("edit-delete"));
-    setEnabled(false);
+    connect(m_ui.keyframe_list, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(slotAdjustKeyframeInfo()));
+    setupParam();
+    m_ui.keyframe_list->header()->resizeSections(QHeaderView::ResizeToContents);
+    connect(m_ui.button_delete, SIGNAL(clicked()), this, SLOT(slotDeleteKeyframe()));
+    connect(m_ui.button_add, SIGNAL(clicked()), this, SLOT(slotAddKeyframe()));
+    connect(m_ui.keyframe_list, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(slotGenerateParams(QTreeWidgetItem *, int)));
+    connect(m_ui.keyframe_list, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(slotSaveCurrentParam(QTreeWidgetItem *, int)));
+    connect(m_ui.keyframe_pos, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustKeyframeValue(int)));
+    m_ui.keyframe_pos->setPageStep(1);
 }
 
-void KeyframeEdit::setupParam(int maxFrame, int minValue, int maxValue, QString keyframes)
+void KeyframeEdit::setupParam(QDomElement e)
 {
-    m_maxFrame = maxFrame;
-    m_min = minValue;
-    m_max = maxValue;
+    if (!e.isNull()) m_param = e;
     m_ui.keyframe_list->clear();
-    QStringList frames = keyframes.split(";");
+    QStringList frames = m_param.attribute("keyframes").split(";", QString::SkipEmptyParts);
     for (int i = 0; i < frames.count(); i++) {
         QString framePos = m_timecode.getTimecodeFromFrames(frames.at(i).section(':', 0, 0).toInt());
-        m_ui.keyframe_list->addTopLevelItem(new QTreeWidgetItem(QStringList() << framePos << frames.at(i).section(':', 1, 1)));
+        QTreeWidgetItem *item = new QTreeWidgetItem(QStringList() << framePos << frames.at(i).section(':', 1, 1));
+        item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
+        m_ui.keyframe_list->addTopLevelItem(item);
     }
+    QTreeWidgetItem *first = m_ui.keyframe_list->topLevelItem(0);
+    if (first) m_ui.keyframe_list->setCurrentItem(first);
+    slotAdjustKeyframeInfo();
 }
 
+void KeyframeEdit::slotDeleteKeyframe()
+{
+    if (m_ui.keyframe_list->topLevelItemCount() < 2) return;
+    QTreeWidgetItem *item = m_ui.keyframe_list->currentItem();
+    if (item) {
+        delete item;
+        slotGenerateParams();
+    }
+}
+
+void KeyframeEdit::slotAddKeyframe()
+{
+    m_ui.keyframe_list->blockSignals(true);
+    int pos2;
+    QTreeWidgetItem *item = m_ui.keyframe_list->currentItem();
+    if (item == NULL) return;
+    int ix = m_ui.keyframe_list->indexOfTopLevelItem(item);
+    int pos1 = m_timecode.getFrameCount(item->text(0), m_timecode.fps());
+    QTreeWidgetItem *below = m_ui.keyframe_list->topLevelItem(ix + 1);
+    if (below == NULL) below = m_ui.keyframe_list->topLevelItem(ix - 1);
+    if (below == NULL) {
+        if (pos1 == 0) pos2 = m_max;
+        else pos2 = 0;
+    } else {
+        pos2 = m_timecode.getFrameCount(below->text(0), m_timecode.fps());
+    }
+
+    int result = (pos1 + pos2) / 2;
+    if (result > pos1) ix++;
+    QTreeWidgetItem *newItem = new QTreeWidgetItem(QStringList() << m_timecode.getTimecodeFromFrames(result) << item->text(1));
+    newItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
+    m_ui.keyframe_list->insertTopLevelItem(ix, newItem);
+    m_ui.keyframe_list->setCurrentItem(newItem);
+    slotAdjustKeyframeInfo();
+    m_ui.keyframe_list->blockSignals(false);
+    slotGenerateParams();
+}
+
+void KeyframeEdit::slotGenerateParams(QTreeWidgetItem *item, int column)
+{
+    if (item) {
+        if (column == 0) {
+            QString val = item->text(0);
+            int pos = m_timecode.getFrameCount(val, m_timecode.fps());
+            if (pos <= 0) {
+                pos = 0;
+                val = m_timecode.getTimecodeFromFrames(pos);
+            }
+            if (pos > m_max) {
+                pos = m_max;
+                val = m_timecode.getTimecodeFromFrames(pos);
+            }
+            QList<QTreeWidgetItem *> duplicates = m_ui.keyframe_list->findItems(val, Qt::MatchExactly, 0);
+            duplicates.removeAll(item);
+            if (!duplicates.isEmpty()) {
+                // Trying to insert a keyframe at existing value, revert it
+                val = m_timecode.getTimecodeFromFrames(m_previousPos);
+            }
+            if (val != item->text(0)) item->setText(0, val);
+        }
+        if (column == 1) {
+            if (item->text(1).toInt() >= m_param.attribute("max").toInt()) item->setText(1, m_param.attribute("max"));
+            if (item->text(1).toInt() <= m_param.attribute("min").toInt()) item->setText(1, m_param.attribute("min"));
+        }
+    }
+    QString keyframes;
+    for (int i = 0; i < m_ui.keyframe_list->topLevelItemCount(); i++) {
+        QTreeWidgetItem *item = m_ui.keyframe_list->topLevelItem(i);
+        keyframes.append(QString::number(m_timecode.getFrameCount(item->text(0), m_timecode.fps())) + ':' + item->text(1) + ';');
+    }
+    m_param.setAttribute("keyframes", keyframes);
+    emit parameterChanged();
+}
+
+void KeyframeEdit::slotAdjustKeyframeInfo()
+{
+    QTreeWidgetItem *item = m_ui.keyframe_list->currentItem();
+    if (!item) return;
+    int min = 0;
+    int max = m_max;
+    QTreeWidgetItem *above = m_ui.keyframe_list->itemAbove(item);
+    QTreeWidgetItem *below = m_ui.keyframe_list->itemBelow(item);
+    if (above) min = m_timecode.getFrameCount(above->text(0), m_timecode.fps()) + 1;
+    if (below) max = m_timecode.getFrameCount(below->text(0), m_timecode.fps()) - 1;
+    m_ui.keyframe_pos->blockSignals(true);
+    m_ui.keyframe_pos->setRange(min, max);
+    m_ui.keyframe_pos->setValue(m_timecode.getFrameCount(item->text(0), m_timecode.fps()));
+    m_ui.keyframe_pos->blockSignals(false);
+}
+
+void KeyframeEdit::slotAdjustKeyframeValue(int value)
+{
+    QTreeWidgetItem *item = m_ui.keyframe_list->currentItem();
+    item->setText(0, m_timecode.getTimecodeFromFrames(value));
+}
+
+void KeyframeEdit::slotSaveCurrentParam(QTreeWidgetItem *item, int column)
+{
+    if (item && column == 0) m_previousPos = m_timecode.getFrameCount(item->text(0), m_timecode.fps());
+}
 
index de334bc3ff445721ad057de4d9de3b6f9021b971..e9bca17bf76d55d9f1e011a4a1af922854198749 100644 (file)
@@ -33,20 +33,26 @@ class KeyframeEdit : public QWidget
 {
     Q_OBJECT
 public:
-    explicit KeyframeEdit(Timecode tc, QWidget* parent = 0);
-    void setupParam(int maxFrame, int minValue, int maxValue, QString keyframes);
+    explicit KeyframeEdit(QDomElement e, int max, Timecode tc, QWidget* parent = 0);
+    void setupParam(QDomElement e = QDomElement());
 
 private:
     Ui::KeyframeEditor_UI m_ui;
-    Timecode m_timecode;
-    int m_min;
+    QDomElement m_param;
     int m_max;
-    int m_maxFrame;
+    Timecode m_timecode;
+    int m_previousPos;
 
 public slots:
 
 
 private slots:
+    void slotDeleteKeyframe();
+    void slotAddKeyframe();
+    void slotGenerateParams(QTreeWidgetItem *item = NULL, int column = -1);
+    void slotAdjustKeyframeInfo();
+    void slotAdjustKeyframeValue(int value);
+    void slotSaveCurrentParam(QTreeWidgetItem *item, int column);
 
 signals:
     void parameterChanged();
index 1da751112a2aa152b74c097cb5711bf7cf8363db..576bf47cf2fad4e79a0aad3f00d7b1be243f6f21 100644 (file)
@@ -6,7 +6,7 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>205</width>
+    <width>157</width>
     <height>103</height>
    </rect>
   </property>
@@ -20,7 +20,7 @@
    <property name="spacing">
     <number>0</number>
    </property>
-   <item row="0" column="0" colspan="3">
+   <item row="0" column="0" colspan="4">
     <widget class="QTreeWidget" name="keyframe_list">
      <property name="alternatingRowColors">
       <bool>true</bool>
     </widget>
    </item>
    <item row="1" column="2">
-    <spacer name="horizontalSpacer">
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Pos</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="3">
+    <widget class="QSlider" name="keyframe_pos">
      <property name="orientation">
       <enum>Qt::Horizontal</enum>
      </property>
-     <property name="sizeHint" stdset="0">
-      <size>
-       <width>118</width>
-       <height>20</height>
-      </size>
-     </property>
-    </spacer>
+    </widget>
    </item>
   </layout>
  </widget>