widgets/fontval_ui.ui
widgets/cutjobdialog_ui.ui
widgets/scenecutdialog_ui.ui
+ widgets/importkeyframesdialog_ui.ui
)
if(OPENGL_FOUND)
#include "commands/changeeffectstatecommand.h"
#include "commands/movegroupcommand.h"
#include "ui_addtrack_ui.h"
+#include "ui_importkeyframesdialog_ui.h"
#include "initeffects.h"
#include "commands/locktrackcommand.h"
#include "commands/groupclipscommand.h"
}
+void CustomTrackView::slotImportClipKeyframes(GRAPHICSRECTITEM type)
+{
+ if (!m_selectionGroup) {
+ emit displayMessage(i18n("You need to select one clip and one transition"), ErrorMessage);
+ return;
+ }
+ // Make sure there is no collision
+ QList<QGraphicsItem *> children = m_selectionGroup->childItems();
+ ClipItem *item;
+ for (int i = 0; i < children.count(); i++) {
+ if (children.at(i)->type() == AVWIDGET) {
+ item = (ClipItem*) children.at(i);
+ break;
+ }
+ }
+ QMap <QString, QString> data = item->baseClip()->analysisData();
+ if (data.isEmpty()) {
+ emit displayMessage(i18n("No keyframe data found in clip"), ErrorMessage);
+ return;
+ }
+ QPointer<QDialog> d = new QDialog(this);
+ Ui::ImportKeyframesDialog_UI ui;
+ ui.setupUi(d);
+
+ // Set up data
+ int ix = 0;
+ QMap<QString, QString>::const_iterator i = data.constBegin();
+ while (i != data.constEnd()) {
+ ui.data_list->insertItem(ix, i.key());
+ ui.data_list->setItemData(ix, i.value(), Qt::UserRole);
+ ++i;
+ ix++;
+ }
+
+ if (d->exec() != QDialog::Accepted) {
+ delete d;
+ return;
+ }
+ QString keyframeData = ui.data_list->itemData(ui.data_list->currentIndex()).toString();
+ QStringList keyframeList = keyframeData.split(';', QString::SkipEmptyParts);
+ QString result;
+ if (ui.import_position->isChecked()) {
+ if (ui.import_size->isChecked()) {
+ foreach(QString key, keyframeList) {
+ if (key.count(':') > 1) result.append(key.section(':', 0, 1));
+ else result.append(key);
+ result.append(';');
+ }
+ }
+ else {
+ foreach(QString key, keyframeList) {
+ result.append(key.section(':', 0, 0));
+ result.append(';');
+ }
+ }
+ }
+ else if (ui.import_size->isChecked()) {
+ foreach(QString key, keyframeList) {
+ result.append(key.section(':', 1, 1));
+ result.append(';');
+ }
+ }
+ emit importKeyframes(type, result);
+ delete d;
+}
+
void updateSnapPoints(AbstractClipItem *selected, QList <GenTime> offsetList = QList <GenTime> (), bool skipSelectedItems = false);
void slotAddEffect(ClipItem *clip, QDomElement effect);
+ void slotImportClipKeyframes(GRAPHICSRECTITEM type);
protected:
virtual void drawBackground(QPainter * painter, const QRectF & rect);
void updateTrackEffectState(int);
/** @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&);
};
#endif
}
}
+ if (xml.hasAttribute("analysisdata")) {
+ QStringList adata = xml.attribute("analysisdata").split('#', QString::SkipEmptyParts);
+ for (int i = 0; i < adata.count(); i++)
+ m_analysisdata.insert(adata.at(i).section('?', 0, 0), adata.at(i).section('?', 1, 1));
+ }
+
KUrl url = KUrl(xml.attribute("resource"));
if (!m_properties.contains("file_hash") && !url.isEmpty()) getFileHash(url.path());
}
clip.setAttribute("cutzones", cuts.join(";"));
}
+ QString adata;
+ if (!m_analysisdata.isEmpty()) {
+ QMapIterator<QString, QString> i(m_analysisdata);
+ while (i.hasNext()) {
+ i.next();
+ //WARNING: a ? and # separator is not a good idea
+ adata.append(i.key() + "?" + i.value() + "#");
+ }
+ }
+ clip.setAttribute("analysisdata", adata);
//kDebug() << "/// CLIP XML: " << doc.toString();
return doc.documentElement();
}
connect (this, SIGNAL(syncEffectsPos(int)), m_paramWidget, SIGNAL(syncEffectsPos(int)));
connect (m_paramWidget, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int)));
connect (m_paramWidget, SIGNAL(seekTimeline(int)), this, SIGNAL(seekTimeline(int)));
+ connect(m_paramWidget, SIGNAL(importClipKeyframes()), this, SIGNAL(importClipKeyframes()));
}
void unGroup(CollapsibleEffect *);
void createRegion(int, KUrl);
void deleteGroup(QDomDocument);
+ void importClipKeyframes();
};
connect(currentEffect, SIGNAL(addEffect(QDomElement)), this , SLOT(slotAddEffect(QDomElement)));
connect(currentEffect, SIGNAL(createRegion(int,KUrl)), this, SLOT(slotCreateRegion(int,KUrl)));
connect(currentEffect, SIGNAL(deleteGroup(QDomDocument)), this , SLOT(slotDeleteGroup(QDomDocument)));
+ connect(currentEffect, SIGNAL(importClipKeyframes()), this, SIGNAL(importClipKeyframes()));
}
void EffectStackView2::slotCheckWheelEventFilter()
void showComments(bool show);
void startFilterJob(ItemInfo info, const QString &clipId, const QString &filterName, const QString &filterParams, const QString&finalFilterName, const QString &consumer, const QString &consumerParams, const QStringList &extraParams);
void addEffect(ClipItem*,QDomElement);
+ void importClipKeyframes(GRAPHICSRECTITEM = AVWIDGET);
};
#endif
m_vbox->addWidget(m_geometryWidget);
m_valueItems[paramName+"geometry"] = m_geometryWidget;
connect(m_geometryWidget, SIGNAL(seekToPos(int)), this, SIGNAL(seekTimeline(int)));
+ connect(m_geometryWidget, SIGNAL(importClipKeyframes()), this, SIGNAL(importClipKeyframes()));
connect(this, SIGNAL(syncEffectsPos(int)), m_geometryWidget, SLOT(slotSyncPosition(int)));
} else {
Geometryval *geo = new Geometryval(m_metaInfo->profile, m_metaInfo->timecode, m_metaInfo->frameSize, 0);
{
return m_needsMonitorEffectScene;
}
+
+void ParameterContainer::setKeyframes(const QString &data)
+{
+ if (!m_geometryWidget) {
+ kDebug()<<" / / NO GEOMETRY WIDGET FOUND FOR IMPORTING DATA";
+ return;
+ }
+ m_geometryWidget->importKeyframes(data);
+
+}
+
void updateParameter(const QString &key, const QString &value);
/** @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);
private slots:
void slotCollectAllParameters();
void showComments(bool);
/** @brief Start an MLT filter job on this clip. */
void startFilterJob(QString filterName, QString filterParams, QString finalFilterName, QString consumer, QString consumerParams, QStringList extra);
-
+ /** @brief Request import of keyframes from clip data. */
+ void importClipKeyframes();
};
#endif
m_paramWidget = new ParameterContainer(d, info, &m_metaInfo, m_baseWidget);
connect (m_paramWidget, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int)), this, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int)));
- connect(m_paramWidget, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QString,QStringList)), this, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QString,QStringList)));
+ connect(m_paramWidget, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QStringList)), this, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QStringList)));
connect (this, SIGNAL(syncEffectsPos(int)), m_paramWidget, SIGNAL(syncEffectsPos(int)));
connect (m_paramWidget, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int)));
connect (m_paramWidget, SIGNAL(seekTimeline(int)), this, SIGNAL(seekTimeline(int)));
+ connect (m_paramWidget, SIGNAL(importClipKeyframes()), this, SIGNAL(importClipKeyframes()));
Q_FOREACH( QSpinBox * sp, m_baseWidget->findChildren<QSpinBox*>() ) {
sp->installEventFilter( this );
return m_paramWidget->needsMonitorEffectScene();
}
+void EffectStackEdit::setKeyframes(const QString &data)
+{
+ if (!m_paramWidget) return;
+ m_paramWidget->setKeyframes(data);
+}
virtual bool eventFilter( QObject * o, QEvent * e );
/** @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);
private:
Monitor *m_monitor;
void showComments(bool show);
void effectStateChanged(bool enabled);
/** @brief Start an MLT filter job on this clip. */
- void startFilterJob(const QString &filterName, const QString &filterParams, const QString &finalFilterName, const QString &consumer, const QString &consumerParams, const QString &properties, const QStringList&extraParams);
+ void startFilterJob(const QString &filterName, const QString &filterParams, const QString &finalFilterName, const QString &consumer, const QString &consumerParams, const QStringList&extraParams);
+ void importClipKeyframes(GRAPHICSRECTITEM = AVWIDGET);
};
#endif
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);
+ menu->addSeparator();
QAction *alignleft = new QAction(KIcon("kdenlive-align-left"), i18n("Align left"), this);
connect(alignleft, SIGNAL(triggered()), this, SLOT(slotMoveLeft()));
menu->addAction(alignleft);
updateMonitorGeometry();
}
+void GeometryWidget::importKeyframes(const QString &data)
+{
+ QStringList list = data.split(';', QString::SkipEmptyParts);
+ 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;
+ QString geom = list.at(i);
+ if (geom.contains('=')) {
+ item.frame(geom.section('=', 0, 0).toInt());
+ }
+ geom = geom.section('=', 1);
+ if (geom.contains('/')) {
+ item.x(geom.section('/', 0, 0).toDouble());
+ item.y(geom.section('/', 1, 1).section(':', 0, 0).toDouble());
+ }
+ else {
+ item.x(0);
+ item.y(0);
+ }
+ if (geom.contains('x')) {
+ item.w(geom.section('x', 0, 0).section(':', 1, 1).toDouble());
+ item.h(geom.section('x', 1, 1).section(':', 0, 0).toDouble());
+ }
+ else {
+ item.w(screenSize.x());
+ item.h(screenSize.y());
+ }
+ //TODO: opacity
+ item.mix(100);
+ m_geometry->insert(item);
+ }
+ emit parameterChanged();
+}
+
#include "geometrywidget.moc"
void updateTimecodeFormat();
/** @brief Sets the size of the original clip. */
void setFrameSize(QPoint size);
-
void addParameter(const QDomElement elem);
+ void importKeyframes(const QString &data);
public slots:
/** @brief Sets up the rect and the geometry object.
signals:
void parameterChanged();
void seekToPos(int);
+ void importClipKeyframes();
};
#endif
disconnect(m_effectStack, SIGNAL(displayMessage(const QString&, int)), this, SLOT(slotGotProgressInfo(const QString&, int)));
disconnect(m_transitionConfig, SIGNAL(transitionUpdated(Transition *, QDomElement)), m_activeTimeline->projectView() , SLOT(slotTransitionUpdated(Transition *, QDomElement)));
disconnect(m_transitionConfig, SIGNAL(seekTimeline(int)), m_activeTimeline->projectView() , SLOT(setCursorPos(int)));
+ disconnect(m_transitionConfig, SIGNAL(importClipKeyframes(GRAPHICSRECTITEM)), m_activeTimeline->projectView() , SLOT(slotImportClipKeyframes(GRAPHICSRECTITEM)));
+
disconnect(m_activeTimeline->projectView(), SIGNAL(activateDocumentMonitor()), m_projectMonitor, SLOT(slotActivateMonitor()));
disconnect(m_activeTimeline, SIGNAL(zoneMoved(int, int)), this, SLOT(slotZoneMoved(int, int)));
disconnect(m_projectList, SIGNAL(loadingIsOver()), m_activeTimeline->projectView(), SLOT(slotUpdateAllThumbs()));
connect(trackView, SIGNAL(updateTracksInfo()), this, SLOT(slotUpdateTrackInfo()));
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(m_projectMonitor, SIGNAL(renderPosition(int)), trackView, SLOT(moveCursorPos(int)));
connect(m_projectMonitor, SIGNAL(zoneUpdated(QPoint)), trackView, SLOT(slotSetZone(QPoint)));
connect(m_projectMonitor, SIGNAL(zoneUpdated(QPoint)), doc, SLOT(setModified()));
connect(m_effectStack, SIGNAL(addEffect(ClipItem*, QDomElement)), trackView->projectView(), SLOT(slotAddEffect(ClipItem*, QDomElement)));
connect(m_effectStack, SIGNAL(changeEffectState(ClipItem*, int, QList <int>, bool)), trackView->projectView(), SLOT(slotChangeEffectState(ClipItem*, int, QList <int>, bool)));
connect(m_effectStack, SIGNAL(changeEffectPosition(ClipItem*, int, QList <int>, int)), trackView->projectView(), SLOT(slotChangeEffectPosition(ClipItem*, int, QList <int>, int)));
+
connect(m_effectStack, SIGNAL(refreshEffectStack(ClipItem*)), trackView->projectView(), SLOT(slotRefreshEffects(ClipItem*)));
- connect(m_effectStack, SIGNAL(seekTimeline(int)), trackView->projectView() , SLOT(seekCursorPos(int)));
+ connect(m_effectStack, SIGNAL(seekTimeline(int)), trackView->projectView(), SLOT(seekCursorPos(int)));
+ connect(m_effectStack, SIGNAL(importClipKeyframes(GRAPHICSRECTITEM)), trackView->projectView(), SLOT(slotImportClipKeyframes(GRAPHICSRECTITEM)));
connect(m_effectStack, SIGNAL(reloadEffects()), this, SLOT(slotReloadEffects()));
connect(m_effectStack, SIGNAL(displayMessage(const QString&, int)), this, SLOT(slotGotProgressInfo(const QString&, int)));
// Transition config signals
connect(m_transitionConfig, SIGNAL(transitionUpdated(Transition *, QDomElement)), trackView->projectView() , SLOT(slotTransitionUpdated(Transition *, QDomElement)));
+ connect(m_transitionConfig, SIGNAL(importClipKeyframes(GRAPHICSRECTITEM)), trackView->projectView() , SLOT(slotImportClipKeyframes(GRAPHICSRECTITEM)));
connect(m_transitionConfig, SIGNAL(seekTimeline(int)), trackView->projectView() , SLOT(seekCursorPos(int)));
connect(trackView->projectView(), SIGNAL(activateDocumentMonitor()), m_projectMonitor, SLOT(slotActivateMonitor()));
}
}
+void MainWindow::slotProcessImportKeyframes(GRAPHICSRECTITEM type, const QString& data)
+{
+ 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);
+ }
+ else {
+ // Error
+ }
+}
+
#include "mainwindow.moc"
void slotChangePalette();
/** @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);
signals:
Q_SCRIPTABLE void abortRenderJob(const QString &url);
// We want to cut scenes
extraParams << "cutscenes";
}
-
+ delete d;
processClipJob(ids, QString(), false, jobParams, i18n("Auto split"), extraParams);
}
else {
}
}
if (returnKey.isEmpty()) {
- emit displayMessage(i18n("No data returned from clip analysis"), 2);
+ emit displayMessage(i18n("No data returned from clip analysis"), ErrorMessage);
return;
}
QStringList returnData = results.value(returnKey).split(';', QString::SkipEmptyParts);
if (returnData.isEmpty()) {
- emit displayMessage(i18n("No data returned from clip analysis"), 2);
+ emit displayMessage(i18n("No data returned from clip analysis"), ErrorMessage);
return;
}
+ emit displayMessage(i18n("Processing data analysis"), InformationMessage);
bool dataProcessed = false;
if (extra.contains("cutscenes")) {
// Check if we want to cut scenes from returned data
vbox1->addWidget(m_effectEdit);
frame->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
connect(m_effectEdit, SIGNAL(seekTimeline(int)), this, SLOT(slotSeekTimeline(int)));
+ connect(m_effectEdit, SIGNAL(importClipKeyframes()), this, SIGNAL(importClipKeyframes()));
+
setEnabled(false);
QList<QStringList> transitionsList;
}
}
+void TransitionSettings::setKeyframes(const QString data)
+{
+ m_effectEdit->setKeyframes(data);
+}
#include "transitionsettings.moc"
void raiseWindow(QWidget*);
void updateProjectFormat(MltVideoProfile profile, Timecode t, const QList <TrackInfo> info);
void updateTimecodeFormat();
+ void setKeyframes(const QString data);
private:
EffectStackEdit *m_effectEdit;
signals:
void transitionUpdated(Transition *, QDomElement);
void seekTimeline(int);
+ void importClipKeyframes(GRAPHICSRECTITEM = TRANSITIONWIDGET);
};
#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ImportKeyframesDialog_UI</class>
+ <widget class="QDialog" name="ImportKeyframesDialog_UI">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>255</width>
+ <height>115</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Scene Cut</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Data to import</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="data_list">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QCheckBox" name="import_position">
+ <property name="text">
+ <string>Position</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QCheckBox" name="import_size">
+ <property name="text">
+ <string>Size</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>218</width>
+ <height>2</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="4" column="1">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ImportKeyframesDialog_UI</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ImportKeyframesDialog_UI</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>