m_geometryWidget(NULL)
{
m_baseWidget = new QWidget(this);
- setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
setFrameStyle(QFrame::NoFrame);
setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding));
QDomNodeList namenode = m_params.elementsByTagName("parameter");
for (int i = 0; i < namenode.count() ; i++) {
QDomNode pa = namenode.item(i);
- QDomNode na = pa.firstChildElement("name");
+ QDomElement na = pa.firstChildElement("name");
QString type = pa.attributes().namedItem("type").nodeValue();
- QString paramName = i18n(na.toElement().text().toUtf8().data());
+ QString paramName = na.isNull() ? pa.attributes().namedItem("name").nodeValue() : i18n(na.text().toUtf8().data());
if (type == "geometry") {
if (!KdenliveSettings::on_monitor_effects()) {
QDomNodeList namenode = m_params.elementsByTagName("parameter");
for (int i = 0; i < namenode.count() ; i++) {
QDomNode pa = namenode.item(i);
- QDomNode na = pa.firstChildElement("name");
+ QDomElement na = pa.firstChildElement("name");
QString type = pa.attributes().namedItem("type").nodeValue();
- QString paramName = i18n(na.toElement().text().toUtf8().data());
+ QString paramName = na.isNull() ? pa.attributes().namedItem("name").nodeValue() : i18n(na.text().toUtf8().data());
if (type == "geometry") {
if (KdenliveSettings::on_monitor_effects()) {
geom->updateTimecodeFormat();
}
break;
- }
- if (type == "position") {
+ } else if (type == "position") {
PositionEdit *posi = ((PositionEdit*)m_valueItems[paramName+"position"]);
posi->updateTimecodeFormat();
break;
+ } else if (type == "roto-spline") {
+ RotoWidget *widget = static_cast<RotoWidget *>(m_valueItems[paramName]);
+ widget->updateTimecodeFormat();
}
}
}
}
}
-void EffectStackEdit::transferParamDesc(const QDomElement d, int pos, int in, int out, bool isEffect)
+void EffectStackEdit::transferParamDesc(const QDomElement d, ItemInfo info, bool isEffect)
{
clearAllItems();
if (m_keyframeEditor) delete m_keyframeEditor;
m_keyframeEditor = NULL;
m_params = d;
- m_in = in;
- m_out = out;
+ m_in = isEffect ? info.cropStart.frames(KdenliveSettings::project_fps()) : info.startPos.frames(KdenliveSettings::project_fps());
+ m_out = isEffect ? (info.cropStart + info.cropDuration).frames(KdenliveSettings::project_fps()) - 1 : info.endPos.frames(KdenliveSettings::project_fps());
if (m_params.isNull()) {
// kDebug() << "// EMPTY EFFECT STACK";
return;
}
#endif
QDomElement e = m_params.toElement();
- const int minFrame = e.attribute("start").toInt();
- const int maxFrame = e.attribute("end").toInt();
+ int minFrame = e.attribute("start").toInt();
+ int maxFrame = e.attribute("end").toInt();
+ // In transitions, maxFrame is in fact one frame after the end of transition
+ if (maxFrame > 0) maxFrame --;
bool disable = d.attribute("disable") == "1" && KdenliveSettings::disable_effect_parameters();
setEnabled(!disable);
QDomElement na = pa.firstChildElement("name");
QDomElement commentElem = pa.firstChildElement("comment");
QString type = pa.attribute("type");
- QString paramName = i18n(na.text().toUtf8().data());
+ QString paramName = na.isNull() ? pa.attribute("name") : i18n(na.text().toUtf8().data());
QString comment;
if (!commentElem.isNull())
comment = i18n(commentElem.text().toUtf8().data());
QString value = pa.attribute("value").isNull() ?
pa.attribute("default") : pa.attribute("value");
- /** Currently supported parameter types are:
- * constant (=double): a slider with an integer value (use the "factor" attribute to divide the value so that you can get a double
- * list: a combobox containing a list of values to choose
- * bool: a checkbox
- * complex: designed for keyframe parameters, but old and not finished, do not use
- * geometry: a rectangle that can be moved & resized, with possible keyframes, used in composite transition
- * keyframe: a list widget with a list of entries (position and value)
- * color: a color chooser button
- * position: a slider representing the position of a frame in the current clip
- * curve: a single curve representing multiple points
- * wipe: a widget designed for the wipe transition, allowing to choose a position (left, right, top,...)
- */
+
+ /** See effects/README for info on the different types */
if (type == "double" || type == "constant") {
- int min;
- int max;
- if (pa.attribute("min").startsWith('%'))
- min = (int) ProfilesDialog::getStringEval(m_profile, pa.attribute("min"));
+ double min;
+ double max;
+ if (pa.attribute("min").contains('%'))
+ min = ProfilesDialog::getStringEval(m_profile, pa.attribute("min"), m_frameSize);
else
- min = pa.attribute("min").toInt();
- if (pa.attribute("max").startsWith('%'))
- max = (int) ProfilesDialog::getStringEval(m_profile, pa.attribute("max"));
+ min = pa.attribute("min").toDouble();
+ if (pa.attribute("max").contains('%'))
+ max = ProfilesDialog::getStringEval(m_profile, pa.attribute("max"), m_frameSize);
else
- max = pa.attribute("max").toInt();
+ max = pa.attribute("max").toDouble();
- DoubleParameterWidget *doubleparam = new DoubleParameterWidget(paramName, (int)(value.toDouble() + 0.5), min, max,
- pa.attribute("default").toInt(), comment, -1, pa.attribute("suffix"), this);
+ DoubleParameterWidget *doubleparam = new DoubleParameterWidget(paramName, value.toDouble(), min, max,
+ pa.attribute("default").toDouble(), comment, -1, pa.attribute("suffix"), pa.attribute("decimals").toInt(), this);
m_vbox->addWidget(doubleparam);
m_valueItems[paramName] = doubleparam;
- connect(doubleparam, SIGNAL(valueChanged(int)), this, SLOT(collectAllParameters()));
+ connect(doubleparam, SIGNAL(valueChanged(double)), this, SLOT(collectAllParameters()));
connect(this, SIGNAL(showComments(bool)), doubleparam, SLOT(slotShowComment(bool)));
} else if (type == "list") {
Listval *lsval = new Listval;
connect(pl, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters()));
} else if (type == "geometry") {
if (KdenliveSettings::on_monitor_effects()) {
- m_geometryWidget = new GeometryWidget(m_monitor, m_timecode, pos, isEffect, m_params.hasAttribute("showrotation"), this);
+ m_geometryWidget = new GeometryWidget(m_monitor, m_timecode, isEffect ? 0 : qMax(0, (int)info.startPos.frames(KdenliveSettings::project_fps())), isEffect, m_params.hasAttribute("showrotation"), this);
m_geometryWidget->setFrameSize(m_frameSize);
m_geometryWidget->slotShowScene(!disable);
// connect this before setupParam to make sure the monitor scene shows up at startup
connect(this, SIGNAL(syncEffectsPos(int)), m_geometryWidget, SLOT(slotSyncPosition(int)));
connect(this, SIGNAL(effectStateChanged(bool)), m_geometryWidget, SLOT(slotShowScene(bool)));
} else {
- Geometryval *geo = new Geometryval(m_profile, m_timecode, m_frameSize, pos);
+ Geometryval *geo = new Geometryval(m_profile, m_timecode, m_frameSize, isEffect ? 0 : qMax(0, (int)info.startPos.frames(KdenliveSettings::project_fps())));
if (minFrame == maxFrame)
geo->setupParam(pa, m_in, m_out);
else
KeyframeEdit *geo;
if (pa.attribute("widget") == "corners") {
// we want a corners-keyframe-widget
- CornersWidget *corners = new CornersWidget(m_monitor, pa, m_in, m_in + m_out, m_timecode, e.attribute("active_keyframe", "-1").toInt(), this);
+ CornersWidget *corners = new CornersWidget(m_monitor, pa, m_in, m_out, m_timecode, e.attribute("active_keyframe", "-1").toInt(), this);
corners->slotShowScene(!disable);
connect(corners, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int)));
connect(this, SIGNAL(effectStateChanged(bool)), corners, SLOT(slotShowScene(bool)));
connect(this, SIGNAL(syncEffectsPos(int)), corners, SLOT(slotSyncPosition(int)));
geo = static_cast<KeyframeEdit *>(corners);
} else {
- geo = new KeyframeEdit(pa, m_in, m_in + m_out, m_timecode, e.attribute("active_keyframe", "-1").toInt());
+ geo = new KeyframeEdit(pa, m_in, m_out, m_timecode, e.attribute("active_keyframe", "-1").toInt());
}
m_vbox->addWidget(geo);
m_valueItems[paramName+"keyframe"] = geo;
meetDependency(paramName, type, EffectsList::parameter(e, depends));
#ifdef QJSON
} else if (type == "roto-spline") {
- RotoWidget *roto = new RotoWidget(value, m_monitor, m_in, m_out, m_timecode, this);
+ RotoWidget *roto = new RotoWidget(value, m_monitor, info, m_timecode, this);
roto->slotShowScene(!disable);
connect(roto, SIGNAL(valueChanged()), this, SLOT(collectAllParameters()));
connect(roto, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int)));
for (int i = 0; i < namenode.count() ; i++) {
QDomNode pa = namenode.item(i);
- QDomNode na = pa.firstChildElement("name");
+ QDomElement na = pa.firstChildElement("name");
QString type = pa.attributes().namedItem("type").nodeValue();
- QString paramName = i18n(na.toElement().text().toUtf8().data());
+ QString paramName = na.isNull() ? pa.attributes().namedItem("name").nodeValue() : i18n(na.text().toUtf8().data());
if (type == "complex")
paramName.append("complex");
else if (type == "position")