From 798233633b721e85bed5f8c120a32556e257365d Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Tue, 17 Nov 2009 16:48:26 +0000 Subject: [PATCH] Improve keyframe editor, fix random keyframe sometimes inserted svn path=/trunk/kdenlive/; revision=4130 --- src/abstractclipitem.cpp | 21 ++++++---- src/clipitem.cpp | 60 +++++++++++++------------- src/effectstackedit.cpp | 2 +- src/keyframeedit.cpp | 34 ++++++++++----- src/keyframeedit.h | 3 +- src/trackview.cpp | 21 +++++----- src/widgets/keyframeeditor_ui.ui | 72 ++++++++++++++++++++++---------- 7 files changed, 132 insertions(+), 81 deletions(-) diff --git a/src/abstractclipitem.cpp b/src/abstractclipitem.cpp index 47905faa..6584428f 100644 --- a/src/abstractclipitem.cpp +++ b/src/abstractclipitem.cpp @@ -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: "< 1) { + if (m_keyframes.count() > 0) { QMap::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")); diff --git a/src/effectstackedit.cpp b/src/effectstackedit.cpp index add62549..e2db15e9 100644 --- a/src/effectstackedit.cpp +++ b/src/effectstackedit.cpp @@ -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); diff --git a/src/keyframeedit.cpp b/src/keyframeedit.cpp index 847caaab..be033ffa 100644 --- a/src/keyframeedit.cpp +++ b/src/keyframeedit.cpp @@ -24,7 +24,7 @@ #include -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)); diff --git a/src/keyframeedit.h b/src/keyframeedit.h index 8de47f02..0aa620d2 100644 --- a/src/keyframeedit.h +++ b/src/keyframeedit.h @@ -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); diff --git a/src/trackview.cpp b/src/trackview.cpp index 16e0da31..b6009c1a 100644 --- a/src/trackview.cpp +++ b/src/trackview.cpp @@ -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; } diff --git a/src/widgets/keyframeeditor_ui.ui b/src/widgets/keyframeeditor_ui.ui index d7023a63..082f86e6 100644 --- a/src/widgets/keyframeeditor_ui.ui +++ b/src/widgets/keyframeeditor_ui.ui @@ -6,18 +6,15 @@ 0 0 - 157 - 103 + 213 + 177 0 - - 0 - - + true @@ -42,34 +39,65 @@ - - - A + + + + + A + + + Qt::NoArrow + + + + + + + D + + + Qt::NoArrow + + + + + + + + + Qt::Horizontal - - Qt::NoArrow + + + 40 + 20 + - + - - + + - D + Position - - Qt::NoArrow + + + + + + Qt::Horizontal - - + + - Pos + Value - - + + Qt::Horizontal -- 2.39.2