From: Jean-Baptiste Mardelle Date: Tue, 30 Oct 2012 14:25:33 +0000 (+0100) Subject: Minor improvements to keyframe widget, allow resetting keyframes X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=f694ca2820be2eb00f589edbbe97f61218df92bd;p=kdenlive Minor improvements to keyframe widget, allow resetting keyframes --- diff --git a/src/customtrackview.cpp b/src/customtrackview.cpp index 3805c6ed..a259b787 100644 --- a/src/customtrackview.cpp +++ b/src/customtrackview.cpp @@ -1024,7 +1024,7 @@ void CustomTrackView::mousePressEvent(QMouseEvent * event) if (selected == false) { m_dragItem = NULL; } - groupSelectedItems(); + groupSelectedItems(QList (), false, false, true); if (m_dragItem) { ClipItem *clip = static_cast (m_dragItem); updateClipTypeActions(dragGroup == NULL ? clip : NULL); @@ -7650,7 +7650,7 @@ void CustomTrackView::slotImportClipKeyframes(GRAPHICSRECTITEM type) result.append(';'); } } - emit importKeyframes(type, result); + emit importKeyframes(type, result, ui.limit_keyframes->isChecked() ? ui.max_keyframes->value() : -1); delete d; } diff --git a/src/customtrackview.h b/src/customtrackview.h index f27f9710..344a01a2 100644 --- a/src/customtrackview.h +++ b/src/customtrackview.h @@ -530,7 +530,7 @@ signals: /** @brief Cursor position changed, repaint ruler.*/ void updateRuler(); /** @brief Send data from a clip to be imported as keyframes for effect / transition.*/ - void importKeyframes(GRAPHICSRECTITEM type, const QString&); + void importKeyframes(GRAPHICSRECTITEM type, const QString&, int maximum); }; #endif diff --git a/src/effectstack/parametercontainer.cpp b/src/effectstack/parametercontainer.cpp index b3820c6f..89256436 100644 --- a/src/effectstack/parametercontainer.cpp +++ b/src/effectstack/parametercontainer.cpp @@ -854,13 +854,13 @@ bool ParameterContainer::needsMonitorEffectScene() const return m_needsMonitorEffectScene; } -void ParameterContainer::setKeyframes(const QString &data) +void ParameterContainer::setKeyframes(const QString &data, int maximum) { if (!m_geometryWidget) { kDebug()<<" / / NO GEOMETRY WIDGET FOUND FOR IMPORTING DATA"; return; } - m_geometryWidget->importKeyframes(data); + m_geometryWidget->importKeyframes(data, maximum); } diff --git a/src/effectstack/parametercontainer.h b/src/effectstack/parametercontainer.h index 92b8dcb5..86bc2cd0 100644 --- a/src/effectstack/parametercontainer.h +++ b/src/effectstack/parametercontainer.h @@ -67,7 +67,7 @@ public: /** @brief Returns true of this effect requires an on monitor adjustable effect scene. */ bool needsMonitorEffectScene() const; /** @brief Set keyframes for this param. */ - void setKeyframes(const QString &data); + void setKeyframes(const QString &data, int maximum); private slots: void slotCollectAllParameters(); diff --git a/src/effectstackedit.cpp b/src/effectstackedit.cpp index 10899110..95b8d37b 100644 --- a/src/effectstackedit.cpp +++ b/src/effectstackedit.cpp @@ -184,9 +184,9 @@ bool EffectStackEdit::needsMonitorEffectScene() const return m_paramWidget->needsMonitorEffectScene(); } -void EffectStackEdit::setKeyframes(const QString &data) +void EffectStackEdit::setKeyframes(const QString &data, int maximum) { if (!m_paramWidget) return; - m_paramWidget->setKeyframes(data); + m_paramWidget->setKeyframes(data, maximum); } diff --git a/src/effectstackedit.h b/src/effectstackedit.h index f7602222..499fe8ed 100644 --- a/src/effectstackedit.h +++ b/src/effectstackedit.h @@ -57,7 +57,7 @@ public: /** @brief Returns true if this transition requires an on monitor scene. */ bool needsMonitorEffectScene() const; /** @brief Set keyframes for this transition. */ - void setKeyframes(const QString &data); + void setKeyframes(const QString &data, int maximum); private: Monitor *m_monitor; diff --git a/src/geometrywidget.cpp b/src/geometrywidget.cpp index fcbb90a6..27c0f8eb 100644 --- a/src/geometrywidget.cpp +++ b/src/geometrywidget.cpp @@ -65,7 +65,7 @@ GeometryWidget::GeometryWidget(Monitor* monitor, Timecode timecode, int clipPos, Setup of timeline and keyframe controls */ - ((QGridLayout *)(m_ui.widgetTimeWrapper->layout()))->addWidget(m_timePos, 1, 6); + ((QGridLayout *)(m_ui.widgetTimeWrapper->layout()))->addWidget(m_timePos, 1, 5); QVBoxLayout *layout = new QVBoxLayout(m_ui.frameTimeline); m_timeline = new KeyframeHelper(m_ui.frameTimeline); @@ -81,15 +81,10 @@ GeometryWidget::GeometryWidget(Monitor* monitor, Timecode timecode, int clipPos, m_ui.buttonNext->setIcon(KIcon("media-skip-forward")); m_ui.buttonNext->setToolTip(i18n("Go to next keyframe")); m_ui.buttonNext->setIconSize(iconSize); - m_ui.buttonAddDelete->setIcon(KIcon("document-new")); + m_ui.buttonAddDelete->setIcon(KIcon("list-add")); m_ui.buttonAddDelete->setToolTip(i18n("Add keyframe")); m_ui.buttonAddDelete->setIconSize(iconSize); - m_ui.buttonSync->setIcon(KIcon("insert-link")); - m_ui.buttonSync->setToolTip(i18n("Synchronize with timeline cursor")); - m_ui.buttonSync->setChecked(KdenliveSettings::transitionfollowcursor()); - m_ui.buttonSync->setIconSize(iconSize); - connect(m_timeline, SIGNAL(requestSeek(int)), this, SLOT(slotRequestSeek(int))); connect(m_timeline, SIGNAL(keyframeMoved(int)), this, SLOT(slotKeyframeMoved(int))); connect(m_timeline, SIGNAL(addKeyframe(int)), this, SLOT(slotAddKeyframe(int))); @@ -98,7 +93,6 @@ GeometryWidget::GeometryWidget(Monitor* monitor, Timecode timecode, int clipPos, connect(m_ui.buttonPrevious, SIGNAL(clicked()), this, SLOT(slotPreviousKeyframe())); connect(m_ui.buttonNext, SIGNAL(clicked()), this, SLOT(slotNextKeyframe())); connect(m_ui.buttonAddDelete, SIGNAL(clicked()), this, SLOT(slotAddDeleteKeyframe())); - connect(m_ui.buttonSync, SIGNAL(toggled(bool)), this, SLOT(slotSetSynchronize(bool))); m_spinX = new DragValue(i18nc("x axis position", "X"), 0, 0, -99000, 99000, -1, QString(), false, this); m_ui.horizontalLayout->addWidget(m_spinX, 0, 0); @@ -115,39 +109,44 @@ GeometryWidget::GeometryWidget(Monitor* monitor, Timecode timecode, int clipPos, m_ui.horizontalLayout->setColumnStretch(4, 10); QMenu *menu = new QMenu(this); - QAction *adjustSize = new QAction(i18n("Adjust to original size"), this); + QAction *adjustSize = new QAction(KIcon("zoom-fit-best"), i18n("Adjust to original size"), this); connect(adjustSize, SIGNAL(triggered()), this, SLOT(slotAdjustToFrameSize())); - menu->addAction(adjustSize); - QAction *fitToWidth = new QAction(i18n("Fit to width"), this); + QAction *fitToWidth = new QAction(KIcon("zoom-fit-width"), i18n("Fit to width"), this); connect(fitToWidth, SIGNAL(triggered()), this, SLOT(slotFitToWidth())); - menu->addAction(fitToWidth); - QAction *fitToHeight = new QAction(i18n("Fit to height"), this); + QAction *fitToHeight = new QAction(KIcon("zoom-fit-height"), i18n("Fit to height"), this); connect(fitToHeight, SIGNAL(triggered()), this, SLOT(slotFitToHeight())); - menu->addAction(fitToHeight); - menu->addSeparator(); + QAction *importKeyframes = new QAction(i18n("Import keyframes from clip"), this); connect(importKeyframes, SIGNAL(triggered()), this, SIGNAL(importClipKeyframes())); menu->addAction(importKeyframes); + QAction *resetKeyframes = new QAction(i18n("Reset keyframes"), this); + connect(resetKeyframes, SIGNAL(triggered()), this, SLOT(slotResetKeyframes())); + menu->addAction(resetKeyframes); menu->addSeparator(); + + QAction *syncTimeline = new QAction(KIcon("insert-link"), i18n("Synchronize with timeline cursor"), this); + syncTimeline->setCheckable(true); + syncTimeline->setChecked(KdenliveSettings::transitionfollowcursor()); + connect(syncTimeline, SIGNAL(toggled(bool)), this, SLOT(slotSetSynchronize(bool))); + menu->addAction(syncTimeline); + QAction *alignleft = new QAction(KIcon("kdenlive-align-left"), i18n("Align left"), this); connect(alignleft, SIGNAL(triggered()), this, SLOT(slotMoveLeft())); - menu->addAction(alignleft); QAction *alignhcenter = new QAction(KIcon("kdenlive-align-hor"), i18n("Center horizontally"), this); connect(alignhcenter, SIGNAL(triggered()), this, SLOT(slotCenterH())); - menu->addAction(alignhcenter); QAction *alignright = new QAction(KIcon("kdenlive-align-right"), i18n("Align right"), this); connect(alignright, SIGNAL(triggered()), this, SLOT(slotMoveRight())); - menu->addAction(alignright); QAction *aligntop = new QAction(KIcon("kdenlive-align-top"), i18n("Align top"), this); connect(aligntop, SIGNAL(triggered()), this, SLOT(slotMoveTop())); - menu->addAction(aligntop); QAction *alignvcenter = new QAction(KIcon("kdenlive-align-vert"), i18n("Center vertically"), this); connect(alignvcenter, SIGNAL(triggered()), this, SLOT(slotCenterV())); - menu->addAction(alignvcenter); QAction *alignbottom = new QAction(KIcon("kdenlive-align-bottom"), i18n("Align bottom"), this); connect(alignbottom, SIGNAL(triggered()), this, SLOT(slotMoveBottom())); - menu->addAction(alignbottom); + m_ui.buttonOptions->setMenu(menu); + m_ui.buttonOptions->setIcon(KIcon("configure")); + m_ui.buttonOptions->setToolTip(i18n("Options")); + m_ui.buttonOptions->setIconSize(iconSize); QHBoxLayout *alignLayout = new QHBoxLayout; alignLayout->setSpacing(0); @@ -180,6 +179,21 @@ GeometryWidget::GeometryWidget(Monitor* monitor, Timecode timecode, int clipPos, alignButton->setDefaultAction(alignbottom); alignButton->setAutoRaise(true); alignLayout->addWidget(alignButton); + + alignButton = new QToolButton; + alignButton->setDefaultAction(adjustSize); + alignButton->setAutoRaise(true); + alignLayout->addWidget(alignButton); + + alignButton = new QToolButton; + alignButton->setDefaultAction(fitToWidth); + alignButton->setAutoRaise(true); + alignLayout->addWidget(alignButton); + + alignButton = new QToolButton; + alignButton->setDefaultAction(fitToHeight); + alignButton->setAutoRaise(true); + alignLayout->addWidget(alignButton); alignLayout->addStretch(10); m_ui.horizontalLayout->addLayout(alignLayout, 1, 0, 1, 4); @@ -238,7 +252,7 @@ GeometryWidget::GeometryWidget(Monitor* monitor, Timecode timecode, int clipPos, GeometryWidget::~GeometryWidget() { - m_scene->setEnabled(true); + m_scene->setEnabled(false); delete m_timePos; delete m_timeline; delete m_spinX; @@ -246,10 +260,14 @@ GeometryWidget::~GeometryWidget() delete m_spinWidth; delete m_spinHeight; delete m_opacity; - m_scene->removeItem(m_rect); - m_scene->removeItem(m_geomPath); - if (m_rect) delete m_rect; - if (m_geomPath) delete m_geomPath; + if (m_rect) { + m_scene->removeItem(m_rect); + delete m_rect; + } + if (m_geomPath) { + m_scene->removeItem(m_geomPath); + delete m_geomPath; + } if (m_previous) delete m_previous; delete m_geometry; m_extraGeometryNames.clear(); @@ -308,7 +326,6 @@ void GeometryWidget::setupParam(const QDomElement elem, int minframe, int maxfra } else { m_ui.widgetTimeWrapper->setHidden(false); m_timeline->setKeyGeometry(m_geometry, m_outPoint - m_inPoint); - m_timeline->update(); m_timePos->setRange(0, m_outPoint - m_inPoint); } @@ -387,14 +404,14 @@ void GeometryWidget::slotPositionChanged(int pos, bool seek) m_rect->setEnabled(false); m_scene->setEnabled(false); m_ui.widgetGeometry->setEnabled(false); - m_ui.buttonAddDelete->setIcon(KIcon("document-new")); + m_ui.buttonAddDelete->setIcon(KIcon("list-add")); m_ui.buttonAddDelete->setToolTip(i18n("Add keyframe")); } else { // keyframe m_rect->setEnabled(true); m_scene->setEnabled(true); m_ui.widgetGeometry->setEnabled(true); - m_ui.buttonAddDelete->setIcon(KIcon("edit-delete")); + m_ui.buttonAddDelete->setIcon(KIcon("list-remove")); m_ui.buttonAddDelete->setToolTip(i18n("Delete keyframe")); } @@ -506,6 +523,7 @@ void GeometryWidget::slotDeleteKeyframe(int pos) } m_timeline->update(); + if (m_geomPath) m_geomPath->setPoints(m_geometry); slotPositionChanged(pos, false); emit parameterChanged(); } @@ -769,20 +787,59 @@ void GeometryWidget::slotFitToHeight() updateMonitorGeometry(); } -void GeometryWidget::importKeyframes(const QString &data) +void GeometryWidget::slotResetKeyframes() +{ + // Delete existing keyframes + Mlt::GeometryItem item; + while (!m_geometry->next_key(&item, 1)) { + m_geometry->remove(item.frame()); + } + + // Create neutral first keyframe + item.frame(0); + item.x(0); + item.y(0); + item.w(m_monitor->render->frameRenderWidth()); + item.h(m_monitor->render->renderHeight()); + item.mix(100); + m_geometry->insert(item); + m_timeline->setKeyGeometry(m_geometry, m_outPoint - m_inPoint); + if (m_geomPath) { + m_scene->removeItem(m_geomPath); + m_geomPath->setPoints(m_geometry); + m_scene->addItem(m_geomPath); + } + slotPositionChanged(-1, false); + emit parameterChanged(); + +} + +void GeometryWidget::importKeyframes(const QString &data, int maximum) { QStringList list = data.split(';', QString::SkipEmptyParts); + if (list.isEmpty()) return; QPoint screenSize = m_frameSize; if (screenSize == QPoint() || screenSize.x() == 0 || screenSize.y() == 0) { screenSize = QPoint(m_monitor->render->frameRenderWidth(), m_monitor->render->renderHeight()); } - for (int i = 0; i < list.count(); i++) { - Mlt::GeometryItem item; + // Clear existing keyframes + Mlt::GeometryItem item; + + while (!m_geometry->next_key(&item, 0)) { + m_geometry->remove(item.frame()); + } + + int offset = 1; + if (maximum > 0 && list.count() > maximum) { + offset = list.count() / maximum; + } + for (int i = 0; i < list.count(); i += offset) { QString geom = list.at(i); if (geom.contains('=')) { item.frame(geom.section('=', 0, 0).toInt()); + geom = geom.section('=', 1); } - geom = geom.section('=', 1); + else item.frame(0); if (geom.contains('/')) { item.x(geom.section('/', 0, 0).toDouble()); item.y(geom.section('/', 1, 1).section(':', 0, 0).toDouble()); @@ -803,7 +860,11 @@ void GeometryWidget::importKeyframes(const QString &data) item.mix(100); m_geometry->insert(item); } + m_timeline->setKeyGeometry(m_geometry, m_outPoint - m_inPoint); + if (m_geomPath) m_geomPath->setPoints(m_geometry); + slotPositionChanged(-1, false); emit parameterChanged(); } + #include "geometrywidget.moc" diff --git a/src/geometrywidget.h b/src/geometrywidget.h index 0ae57f73..cdd01cd6 100644 --- a/src/geometrywidget.h +++ b/src/geometrywidget.h @@ -58,7 +58,7 @@ public: /** @brief Sets the size of the original clip. */ void setFrameSize(QPoint size); void addParameter(const QDomElement elem); - void importKeyframes(const QString &data); + void importKeyframes(const QString &data, int maximum); public slots: /** @brief Sets up the rect and the geometry object. @@ -68,6 +68,7 @@ public slots: void setupParam(const QDomElement elem, int minframe, int maxframe); /** @brief Updates position of the local timeline to @param relTimelinePos. */ void slotSyncPosition(int relTimelinePos); + void slotResetKeyframes(); private: Ui::GeometryWidget_UI m_ui; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 9139b6d2..82490f7f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2568,7 +2568,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha connect(trackView, SIGNAL(mousePosition(int)), this, SLOT(slotUpdateMousePosition(int))); connect(trackView->projectView(), SIGNAL(forceClipProcessing(const QString &)), m_projectList, SLOT(slotForceProcessing(const QString &))); - connect(trackView->projectView(), SIGNAL(importKeyframes(GRAPHICSRECTITEM, const QString&)), this, SLOT(slotProcessImportKeyframes(GRAPHICSRECTITEM, const QString&))); + connect(trackView->projectView(), SIGNAL(importKeyframes(GRAPHICSRECTITEM, const QString&, int)), this, SLOT(slotProcessImportKeyframes(GRAPHICSRECTITEM, const QString&, int))); connect(m_projectMonitor, SIGNAL(renderPosition(int)), trackView, SLOT(moveCursorPos(int))); connect(m_projectMonitor, SIGNAL(zoneUpdated(QPoint)), trackView, SLOT(slotSetZone(QPoint))); @@ -4573,14 +4573,14 @@ void MainWindow::slotSaveTimelineClip() } } -void MainWindow::slotProcessImportKeyframes(GRAPHICSRECTITEM type, const QString& data) +void MainWindow::slotProcessImportKeyframes(GRAPHICSRECTITEM type, const QString& data, int maximum) { if (type == AVWIDGET) { // This data should be sent to the effect stack } else if (type == TRANSITIONWIDGET) { // This data should be sent to the transition stack - m_transitionConfig->setKeyframes(data); + m_transitionConfig->setKeyframes(data, maximum); } else { // Error diff --git a/src/mainwindow.h b/src/mainwindow.h index 4833d77b..9efa6e4c 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -567,7 +567,7 @@ private slots: /** @brief Save current timeline clip as mlt playlist. */ void slotSaveTimelineClip(); /** @brief Process keyframe data sent from a clip to effect / transition stack. */ - void slotProcessImportKeyframes(GRAPHICSRECTITEM type, const QString& data); + void slotProcessImportKeyframes(GRAPHICSRECTITEM type, const QString& data, int maximum); signals: Q_SCRIPTABLE void abortRenderJob(const QString &url); diff --git a/src/transitionsettings.cpp b/src/transitionsettings.cpp index 312cf60d..996d8a89 100644 --- a/src/transitionsettings.cpp +++ b/src/transitionsettings.cpp @@ -246,9 +246,9 @@ void TransitionSettings::slotCheckMonitorPosition(int renderPos) } } -void TransitionSettings::setKeyframes(const QString data) +void TransitionSettings::setKeyframes(const QString data, int maximum) { - m_effectEdit->setKeyframes(data); + m_effectEdit->setKeyframes(data, maximum); } #include "transitionsettings.moc" diff --git a/src/transitionsettings.h b/src/transitionsettings.h index 46e6eef0..efe0188e 100644 --- a/src/transitionsettings.h +++ b/src/transitionsettings.h @@ -37,7 +37,7 @@ public: void raiseWindow(QWidget*); void updateProjectFormat(MltVideoProfile profile, Timecode t, const QList info); void updateTimecodeFormat(); - void setKeyframes(const QString data); + void setKeyframes(const QString data, int maximum); private: EffectStackEdit *m_effectEdit; diff --git a/src/widgets/geometrywidget_ui.ui b/src/widgets/geometrywidget_ui.ui index b83e2f56..d412e48b 100644 --- a/src/widgets/geometrywidget_ui.ui +++ b/src/widgets/geometrywidget_ui.ui @@ -6,8 +6,8 @@ 0 0 - 129 - 85 + 312 + 183 @@ -23,18 +23,31 @@ 0 - - - - ... + + + + QToolButton::InstantPopup true - - + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + ... @@ -43,8 +56,11 @@ - - + + + + + ... @@ -53,20 +69,17 @@ - - - - Qt::Horizontal + + + + ... - - - 40 - 20 - + + true - + - + @@ -88,32 +101,6 @@ - - - - - - - ... - - - true - - - true - - - - - - - QFrame::Raised - - - Qt::Vertical - - - @@ -140,19 +127,6 @@ 0 - - - - Options - - - QToolButton::InstantPopup - - - false - - - @@ -164,7 +138,6 @@ buttonPrevious buttonAddDelete buttonNext - buttonSync diff --git a/src/widgets/importkeyframesdialog_ui.ui b/src/widgets/importkeyframesdialog_ui.ui index dd057f8f..00413bfb 100644 --- a/src/widgets/importkeyframesdialog_ui.ui +++ b/src/widgets/importkeyframesdialog_ui.ui @@ -6,20 +6,16 @@ 0 0 - 255 - 115 + 248 + 163 - Scene Cut + Import Keyframes - - - - Data to import - - + + @@ -31,6 +27,53 @@ + + + + Qt::Vertical + + + + 218 + 2 + + + + + + + + + + Limit keyframes number + + + + + + + false + + + 1 + + + 1000 + + + 10 + + + + + + + + + Size + + + @@ -41,27 +84,14 @@ - - + + - Size + Data to import - - - - Qt::Vertical - - - - 218 - 2 - - - - - + Qt::Horizontal @@ -107,5 +137,21 @@ + + limit_keyframes + toggled(bool) + max_keyframes + setEnabled(bool) + + + 86 + 94 + + + 207 + 94 + + +