]> git.sesse.net Git - kdenlive/blob - src/effectstackedit.cpp
Use new parametercontainer widget for transitions
[kdenlive] / src / effectstackedit.cpp
1 /***************************************************************************
2                           effecstackedit.cpp  -  description
3                              -------------------
4     begin                : Feb 15 2008
5     copyright            : (C) 2008 by Marco Gittler
6     email                : g.marco@freenet.de
7  ***************************************************************************/
8
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17
18 #include "effectstackedit.h"
19 #include "ui_listval_ui.h"
20 #include "ui_boolval_ui.h"
21 #include "ui_wipeval_ui.h"
22 #include "ui_urlval_ui.h"
23 #include "ui_keywordval_ui.h"
24 #include "ui_fontval_ui.h"
25 #include "complexparameter.h"
26 #include "geometryval.h"
27 #include "positionedit.h"
28 #include "projectlist.h"
29 #include "effectslist.h"
30 #include "kdenlivesettings.h"
31 #include "profilesdialog.h"
32 #include "kis_curve_widget.h"
33 #include "kis_cubic_curve.h"
34 #include "choosecolorwidget.h"
35 #include "geometrywidget.h"
36 #include "colortools.h"
37 #include "doubleparameterwidget.h"
38 #include "cornerswidget.h"
39 #include "beziercurve/beziersplinewidget.h"
40 #ifdef USE_QJSON
41 #include "rotoscoping/rotowidget.h"
42 #endif
43
44 #include <KDebug>
45 #include <KLocale>
46 #include <KFileDialog>
47 #include <KColorScheme>
48
49 #include <QVBoxLayout>
50 #include <QLabel>
51 #include <QPushButton>
52 #include <QCheckBox>
53 #include <QScrollArea>
54
55 // For QDomNode debugging (output into files); leaving here as sample code.
56 //#define DEBUG_ESE
57
58
59 class Boolval: public QWidget, public Ui::Boolval_UI
60 {
61 };
62
63 class Listval: public QWidget, public Ui::Listval_UI
64 {
65 };
66
67 class Wipeval: public QWidget, public Ui::Wipeval_UI
68 {
69 };
70
71 class Urlval: public QWidget, public Ui::Urlval_UI
72 {
73 };
74
75 class Keywordval: public QWidget, public Ui::Keywordval_UI
76 {
77 };
78
79 class Fontval: public QWidget, public Ui::Fontval_UI
80 {
81 };
82
83 QMap<QString, QImage> EffectStackEdit::iconCache;
84
85 EffectStackEdit::EffectStackEdit(Monitor *monitor, QWidget *parent) :
86     QScrollArea(parent),
87     m_in(0),
88     m_out(0),
89     m_keyframeEditor(NULL),
90     m_monitor(monitor),
91     m_geometryWidget(NULL),
92     m_paramWidget(NULL)
93 {
94     m_baseWidget = new QWidget(this);
95     m_metaInfo.monitor = monitor;
96     m_metaInfo.trackMode = false;
97     setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
98     setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
99     setFrameStyle(QFrame::NoFrame);
100     setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding));
101     
102     QPalette p = palette();
103     KColorScheme scheme(p.currentColorGroup(), KColorScheme::View, KSharedConfig::openConfig(KdenliveSettings::colortheme()));
104     QColor dark_bg = scheme.shade(KColorScheme::DarkShade);
105     QColor selected_bg = scheme.decoration(KColorScheme::FocusColor).color();
106     QColor hover_bg = scheme.decoration(KColorScheme::HoverColor).color();    
107     QColor light_bg = scheme.shade(KColorScheme::LightShade);
108     
109     QString stylesheet(QString("QProgressBar:horizontal {border: 1px solid %1;border-radius:0px;border-top-left-radius: 4px;border-bottom-left-radius: 4px;border-right: 0px;background:%4;padding: 0px;text-align:left center}\
110                                 QProgressBar:horizontal#dragOnly {background: %1} QProgressBar:horizontal:hover#dragOnly {background: %3} QProgressBar:horizontal:hover {border: 1px solid %3;border-right: 0px;}\
111                                 QProgressBar::chunk:horizontal {background: %1;} QProgressBar::chunk:horizontal:hover {background: %3;}\
112                                 QProgressBar:horizontal[inTimeline=\"true\"] { border: 1px solid %2;border-right: 0px;background: %4;padding: 0px;text-align:left center } QProgressBar::chunk:horizontal[inTimeline=\"true\"] {background: %2;}\
113                                 QAbstractSpinBox#dragBox {border: 1px solid %1;border-top-right-radius: 4px;border-bottom-right-radius: 4px;padding-right:0px;} QAbstractSpinBox::down-button#dragBox {width:0px;padding:0px;}\
114                                 QAbstractSpinBox::up-button#dragBox {width:0px;padding:0px;} QAbstractSpinBox[inTimeline=\"true\"]#dragBox { border: 1px solid %2;} QAbstractSpinBox:hover#dragBox {border: 1px solid %3;} ")
115                                 .arg(dark_bg.name()).arg(selected_bg.name()).arg(hover_bg.name()).arg(light_bg.name()));
116     setStyleSheet(stylesheet);
117     setWidget(m_baseWidget);   
118     /*m_vbox = new QVBoxLayout(m_baseWidget);
119     m_vbox->setContentsMargins(0, 0, 0, 0);
120     m_vbox->setSpacing(2);    */
121     setWidgetResizable(true);
122 }
123
124 EffectStackEdit::~EffectStackEdit()
125 {
126     iconCache.clear();
127     delete m_baseWidget;
128 }
129
130 Monitor *EffectStackEdit::monitor()
131 {
132     return m_metaInfo.monitor;
133 }
134
135 void EffectStackEdit::updateProjectFormat(MltVideoProfile profile, Timecode t)
136 {
137     m_metaInfo.profile = profile;
138     m_metaInfo.timecode = t;
139 }
140
141 void EffectStackEdit::setFrameSize(QPoint p)
142 {
143     m_metaInfo.frameSize = p;
144     /*
145     m_frameSize = p;
146     QDomNodeList namenode = m_params.elementsByTagName("parameter");
147     for (int i = 0; i < namenode.count() ; i++) {
148         QDomNode pa = namenode.item(i);
149         QDomElement na = pa.firstChildElement("name");
150         QString type = pa.attributes().namedItem("type").nodeValue();
151         QString paramName = na.isNull() ? pa.attributes().namedItem("name").nodeValue() : i18n(na.text().toUtf8().data());
152
153         if (type == "geometry") {
154             if (!KdenliveSettings::on_monitor_effects()) {
155                 Geometryval *geom = ((Geometryval*)m_valueItems[paramName+"geometry"]);
156                 geom->setFrameSize(m_frameSize);
157                 break;
158             }
159             else {
160                 if (m_geometryWidget) m_geometryWidget->setFrameSize(m_frameSize);
161                 break;
162             }
163         }
164     }*/
165 }
166
167 void EffectStackEdit::updateTimecodeFormat()
168 {
169     if (m_paramWidget) m_paramWidget->updateTimecodeFormat();
170 }
171
172 void EffectStackEdit::meetDependency(const QString& name, QString type, QString value)
173 {
174     if (type == "curve") {
175         KisCurveWidget *curve = (KisCurveWidget*)m_valueItems[name];
176         if (curve) {
177             int color = value.toInt();
178             curve->setPixmap(QPixmap::fromImage(ColorTools::rgbCurvePlane(curve->size(), (ColorTools::ColorsRGB)(color == 3 ? 4 : color), 0.8)));
179         }
180     } else if (type == "bezier_spline") {
181         BezierSplineWidget *widget = (BezierSplineWidget*)m_valueItems[name];
182         if (widget) {
183             widget->setMode((BezierSplineWidget::CurveModes)((int)(value.toDouble() * 10)));
184         }
185     }
186 }
187
188 void EffectStackEdit::updateParameter(const QString &name, const QString &value)
189 {
190     m_params.setAttribute(name, value);
191
192     if (name == "disable") {
193         // if effect is disabled, disable parameters widget
194         bool enabled = value.toInt() == 0 || !KdenliveSettings::disable_effect_parameters();
195         setEnabled(enabled);
196         emit effectStateChanged(enabled);
197     }
198 }
199
200 void EffectStackEdit::transferParamDesc(const QDomElement &d, ItemInfo info, bool /*isEffect*/)
201 {
202     if (m_paramWidget) delete m_paramWidget;
203     m_paramWidget = new ParameterContainer(d, info, &m_metaInfo, 0, m_baseWidget);
204     connect (m_paramWidget, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int)), this, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int)));
205     
206     connect(m_paramWidget, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QString)), this, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QString)));
207     
208     connect (this, SIGNAL(syncEffectsPos(int)), m_paramWidget, SIGNAL(syncEffectsPos(int)));
209     connect (m_paramWidget, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int)));
210     connect (m_paramWidget, SIGNAL(seekTimeline(int)), this, SIGNAL(seekTimeline(int)));
211     return;
212     /*
213     //clearAllItems();
214     if (m_keyframeEditor) delete m_keyframeEditor;
215     m_keyframeEditor = NULL;
216     m_params = d;
217     m_in = isEffect ? info.cropStart.frames(KdenliveSettings::project_fps()) : info.startPos.frames(KdenliveSettings::project_fps());
218     m_out = isEffect ? (info.cropStart + info.cropDuration).frames(KdenliveSettings::project_fps()) - 1 : info.endPos.frames(KdenliveSettings::project_fps());
219     if (m_params.isNull()) {
220 //         kDebug() << "// EMPTY EFFECT STACK";
221         return;
222     }
223
224     QDomNodeList namenode = m_params.elementsByTagName("parameter");
225 #ifdef DEBUG_ESE
226     QFile debugFile("/tmp/namenodes.txt");
227     if (debugFile.open(QFile::WriteOnly | QFile::Truncate)) {
228         QTextStream out(&debugFile);
229         QTextStream out2(stdout);
230         for (int i = 0; i < namenode.size(); i++) {
231             out << i << ": \n";
232             namenode.at(i).save(out, 2);
233             out2 << i << ": \n";
234             namenode.at(i).save(out2, 2);
235         }
236     }
237 #endif
238     int minFrame = d.attribute("start").toInt();
239     int maxFrame = d.attribute("end").toInt();
240     // In transitions, maxFrame is in fact one frame after the end of transition
241     if (maxFrame > 0) maxFrame --;
242
243     bool disable = d.attribute("disable") == "1" && KdenliveSettings::disable_effect_parameters();
244     setEnabled(!disable);
245
246     bool stretch = true;
247
248
249     for (int i = 0; i < namenode.count() ; i++) {
250         QDomElement pa = namenode.item(i).toElement();
251         QDomElement na = pa.firstChildElement("name");
252         QDomElement commentElem = pa.firstChildElement("comment");
253         QString type = pa.attribute("type");
254         QString paramName = na.isNull() ? pa.attribute("name") : i18n(na.text().toUtf8().data());
255         QString comment;
256         if (!commentElem.isNull())
257             comment = i18n(commentElem.text().toUtf8().data());
258         QString value = pa.attribute("value").isNull() ?
259                         pa.attribute("default") : pa.attribute("value");
260
261
262       
263
264         if (type == "double" || type == "constant") {
265             double min;
266             double max;
267             if (pa.attribute("min").contains('%'))
268                 min = ProfilesDialog::getStringEval(m_profile, pa.attribute("min"), m_frameSize);
269             else
270                 min = pa.attribute("min").toDouble();
271             if (pa.attribute("max").contains('%'))
272                 max = ProfilesDialog::getStringEval(m_profile, pa.attribute("max"), m_frameSize);
273             else
274                 max = pa.attribute("max").toDouble();
275
276             DoubleParameterWidget *doubleparam = new DoubleParameterWidget(paramName, value.toDouble(), min, max,
277                     pa.attribute("default").toDouble(), comment, -1, pa.attribute("suffix"), pa.attribute("decimals").toInt(), this);
278             m_vbox->addWidget(doubleparam);
279             m_valueItems[paramName] = doubleparam;
280             connect(doubleparam, SIGNAL(valueChanged(double)), this, SLOT(collectAllParameters()));
281             connect(this, SIGNAL(showComments(bool)), doubleparam, SLOT(slotShowComment(bool)));
282         } else if (type == "list") {
283             Listval *lsval = new Listval;
284             QWidget * toFillin = new QWidget(m_baseWidget);
285             lsval->setupUi(toFillin);
286             m_vbox->addWidget(toFillin);
287             QStringList listitems = pa.attribute("paramlist").split(';');
288             if (listitems.count() == 1) {
289                 // probably custom effect created before change to ';' as separator
290                 listitems = pa.attribute("paramlist").split(',');
291             }
292             QDomElement list = pa.firstChildElement("paramlistdisplay");
293             QStringList listitemsdisplay;
294             if (!list.isNull()) {
295                 listitemsdisplay = i18n(list.text().toUtf8().data()).split(',');
296             } else {
297                 listitemsdisplay = i18n(pa.attribute("paramlistdisplay").toUtf8().data()).split(',');
298             }
299             if (listitemsdisplay.count() != listitems.count())
300                 listitemsdisplay = listitems;
301             lsval->list->setIconSize(QSize(30, 30));
302             for (int i = 0; i < listitems.count(); i++) {
303                 lsval->list->addItem(listitemsdisplay.at(i), listitems.at(i));
304                 QString entry = listitems.at(i);
305                 if (!entry.isEmpty() && (entry.endsWith(".png") || entry.endsWith(".pgm"))) {
306                     if (!EffectStackEdit::iconCache.contains(entry)) {
307                         QImage pix(entry);
308                         EffectStackEdit::iconCache[entry] = pix.scaled(30, 30);
309                     }
310                     lsval->list->setItemIcon(i, QPixmap::fromImage(iconCache[entry]));
311                 }
312             }
313             if (!value.isEmpty()) lsval->list->setCurrentIndex(listitems.indexOf(value));
314             lsval->name->setText(paramName);
315             lsval->labelComment->setText(comment);
316             lsval->widgetComment->setHidden(true);
317             m_valueItems[paramName] = lsval;
318             connect(lsval->list, SIGNAL(currentIndexChanged(int)) , this, SLOT(collectAllParameters()));
319             if (!comment.isEmpty())
320                 connect(this, SIGNAL(showComments(bool)), lsval->widgetComment, SLOT(setVisible(bool)));
321             m_uiItems.append(lsval);
322         } else if (type == "bool") {
323             Boolval *bval = new Boolval;
324             QWidget * toFillin = new QWidget(m_baseWidget);
325             bval->setupUi(toFillin);
326             m_vbox->addWidget(toFillin);
327             bval->checkBox->setCheckState(value == "0" ? Qt::Unchecked : Qt::Checked);
328             bval->name->setText(paramName);
329             bval->labelComment->setText(comment);
330             bval->widgetComment->setHidden(true);
331             m_valueItems[paramName] = bval;
332             connect(bval->checkBox, SIGNAL(stateChanged(int)) , this, SLOT(collectAllParameters()));
333             if (!comment.isEmpty())
334                 connect(this, SIGNAL(showComments(bool)), bval->widgetComment, SLOT(setVisible(bool)));
335             m_uiItems.append(bval);
336         } else if (type == "complex") {
337             ComplexParameter *pl = new ComplexParameter;
338             pl->setupParam(d, pa.attribute("name"), 0, 100);
339             m_vbox->addWidget(pl);
340             m_valueItems[paramName+"complex"] = pl;
341             connect(pl, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters()));
342         } else if (type == "geometry") {
343             if (KdenliveSettings::on_monitor_effects()) {
344                 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);
345                 m_geometryWidget->setFrameSize(m_frameSize);
346                 m_geometryWidget->slotShowScene(!disable);
347                 // connect this before setupParam to make sure the monitor scene shows up at startup
348                 connect(m_geometryWidget, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int)));
349                 connect(m_geometryWidget, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters()));
350                 if (minFrame == maxFrame)
351                     m_geometryWidget->setupParam(pa, m_in, m_out);
352                 else
353                     m_geometryWidget->setupParam(pa, minFrame, maxFrame);
354                 m_vbox->addWidget(m_geometryWidget);
355                 m_valueItems[paramName+"geometry"] = m_geometryWidget;
356                 connect(m_geometryWidget, SIGNAL(seekToPos(int)), this, SIGNAL(seekTimeline(int)));
357                 connect(this, SIGNAL(syncEffectsPos(int)), m_geometryWidget, SLOT(slotSyncPosition(int)));
358                 connect(this, SIGNAL(effectStateChanged(bool)), m_geometryWidget, SLOT(slotShowScene(bool)));
359             } else {
360                 Geometryval *geo = new Geometryval(m_profile, m_timecode, m_frameSize, isEffect ? 0 : qMax(0, (int)info.startPos.frames(KdenliveSettings::project_fps())));
361                 if (minFrame == maxFrame)
362                     geo->setupParam(pa, m_in, m_out);
363                 else
364                     geo->setupParam(pa, minFrame, maxFrame);
365                 m_vbox->addWidget(geo);
366                 m_valueItems[paramName+"geometry"] = geo;
367                 connect(geo, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters()));
368                 connect(geo, SIGNAL(seekToPos(int)), this, SIGNAL(seekTimeline(int)));
369                 connect(this, SIGNAL(syncEffectsPos(int)), geo, SLOT(slotSyncPosition(int)));
370             }
371         } else if (type == "addedgeometry") {
372             // this is a parameter that should be linked to the geometry widget, for example rotation, shear, ...
373             if (m_geometryWidget) m_geometryWidget->addParameter(pa);
374         } else if (type == "keyframe" || type == "simplekeyframe") {
375             // keyframe editor widget
376             if (m_keyframeEditor == NULL) {
377                 KeyframeEdit *geo;
378                 if (pa.attribute("widget") == "corners") {
379                     // we want a corners-keyframe-widget
380                     CornersWidget *corners = new CornersWidget(m_monitor, pa, m_in, m_out, m_timecode, d.attribute("active_keyframe", "-1").toInt(), this);
381                     corners->slotShowScene(!disable);
382                     connect(corners, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int)));
383                     connect(this, SIGNAL(effectStateChanged(bool)), corners, SLOT(slotShowScene(bool)));
384                     connect(this, SIGNAL(syncEffectsPos(int)), corners, SLOT(slotSyncPosition(int)));
385                     geo = static_cast<KeyframeEdit *>(corners);
386                 } else {
387                     geo = new KeyframeEdit(pa, m_in, m_out, m_timecode, d.attribute("active_keyframe", "-1").toInt());
388                 }
389                 m_vbox->addWidget(geo);
390                 m_valueItems[paramName+"keyframe"] = geo;
391                 m_keyframeEditor = geo;
392                 connect(geo, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters()));
393                 connect(geo, SIGNAL(seekToPos(int)), this, SIGNAL(seekTimeline(int)));
394                 connect(this, SIGNAL(showComments(bool)), geo, SIGNAL(showComments(bool)));
395             } else {
396                 // we already have a keyframe editor, so just add another column for the new param
397                 m_keyframeEditor->addParameter(pa);
398             }
399         } else if (type == "color") {
400             ChooseColorWidget *choosecolor = new ChooseColorWidget(paramName, value, this);
401             choosecolor->setAlphaChannelEnabled(pa.attribute("alpha") == "1");
402             m_vbox->addWidget(choosecolor);
403             m_valueItems[paramName] = choosecolor;
404             connect(choosecolor, SIGNAL(displayMessage(const QString&, int)), this, SIGNAL(displayMessage(const QString&, int)));
405             connect(choosecolor, SIGNAL(modified()) , this, SLOT(collectAllParameters()));
406         } else if (type == "position") {
407             int pos = value.toInt();
408             if (d.attribute("id") == "fadein" || d.attribute("id") == "fade_from_black") {
409                 pos = pos - m_in;
410             } else if (d.attribute("id") == "fadeout" || d.attribute("id") == "fade_to_black") {
411                 // fadeout position starts from clip end
412                 pos = m_out - pos;
413             }
414             PositionEdit *posedit = new PositionEdit(paramName, pos, 0, m_out - m_in, m_timecode);
415             m_vbox->addWidget(posedit);
416             m_valueItems[paramName+"position"] = posedit;
417             connect(posedit, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters()));
418         } else if (type == "curve") {
419             KisCurveWidget *curve = new KisCurveWidget(this);
420             curve->setMaxPoints(pa.attribute("max").toInt());
421             QList<QPointF> points;
422             int number;
423             if (d.attribute("version").toDouble() > 0.2) {
424                 number = EffectsList::parameter(d, pa.attribute("number")).toDouble() * 10;
425             } else {
426                 number = EffectsList::parameter(d, pa.attribute("number")).toInt();
427             }
428             QString inName = pa.attribute("inpoints");
429             QString outName = pa.attribute("outpoints");
430             int start = pa.attribute("min").toInt();
431             for (int j = start; j <= number; j++) {
432                 QString in = inName;
433                 in.replace("%i", QString::number(j));
434                 QString out = outName;
435                 out.replace("%i", QString::number(j));
436                 points << QPointF(EffectsList::parameter(d, in).toDouble(), EffectsList::parameter(d, out).toDouble());
437             }
438             if (!points.isEmpty())
439                 curve->setCurve(KisCubicCurve(points));
440             QSpinBox *spinin = new QSpinBox();
441             spinin->setRange(0, 1000);
442             QSpinBox *spinout = new QSpinBox();
443             spinout->setRange(0, 1000);
444             curve->setupInOutControls(spinin, spinout, 0, 1000);
445             m_vbox->addWidget(curve);
446             m_vbox->addWidget(spinin);
447             m_vbox->addWidget(spinout);
448
449             connect(curve, SIGNAL(modified()), this, SLOT(collectAllParameters()));
450             m_valueItems[paramName] = curve;
451
452             QString depends = pa.attribute("depends");
453             if (!depends.isEmpty())
454                 meetDependency(paramName, type, EffectsList::parameter(d, depends));
455         } else if (type == "bezier_spline") {
456             BezierSplineWidget *widget = new BezierSplineWidget(value, this);
457             stretch = false;
458             m_vbox->addWidget(widget);
459             m_valueItems[paramName] = widget;
460             connect(widget, SIGNAL(modified()), this, SLOT(collectAllParameters()));
461             QString depends = pa.attribute("depends");
462             if (!depends.isEmpty())
463                 meetDependency(paramName, type, EffectsList::parameter(d, depends));
464 #ifdef USE_QJSON
465         } else if (type == "roto-spline") {
466             RotoWidget *roto = new RotoWidget(value, m_monitor, info, m_timecode, this);
467             roto->slotShowScene(!disable);
468             connect(roto, SIGNAL(valueChanged()), this, SLOT(collectAllParameters()));
469             connect(roto, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int)));
470             connect(roto, SIGNAL(seekToPos(int)), this, SIGNAL(seekTimeline(int)));
471             connect(this, SIGNAL(syncEffectsPos(int)), roto, SLOT(slotSyncPosition(int)));
472             connect(this, SIGNAL(effectStateChanged(bool)), roto, SLOT(slotShowScene(bool)));
473             m_vbox->addWidget(roto);
474             m_valueItems[paramName] = roto;
475 #endif
476         } else if (type == "wipe") {
477             Wipeval *wpval = new Wipeval;
478             QWidget * toFillin = new QWidget(m_baseWidget);
479             wpval->setupUi(toFillin);
480             m_vbox->addWidget(toFillin);
481             wipeInfo w = getWipeInfo(value);
482             switch (w.start) {
483             case UP:
484                 wpval->start_up->setChecked(true);
485                 break;
486             case DOWN:
487                 wpval->start_down->setChecked(true);
488                 break;
489             case RIGHT:
490                 wpval->start_right->setChecked(true);
491                 break;
492             case LEFT:
493                 wpval->start_left->setChecked(true);
494                 break;
495             default:
496                 wpval->start_center->setChecked(true);
497                 break;
498             }
499             switch (w.end) {
500             case UP:
501                 wpval->end_up->setChecked(true);
502                 break;
503             case DOWN:
504                 wpval->end_down->setChecked(true);
505                 break;
506             case RIGHT:
507                 wpval->end_right->setChecked(true);
508                 break;
509             case LEFT:
510                 wpval->end_left->setChecked(true);
511                 break;
512             default:
513                 wpval->end_center->setChecked(true);
514                 break;
515             }
516             wpval->start_transp->setValue(w.startTransparency);
517             wpval->end_transp->setValue(w.endTransparency);
518             m_valueItems[paramName] = wpval;
519             connect(wpval->end_up, SIGNAL(clicked()), this, SLOT(collectAllParameters()));
520             connect(wpval->end_down, SIGNAL(clicked()), this, SLOT(collectAllParameters()));
521             connect(wpval->end_left, SIGNAL(clicked()), this, SLOT(collectAllParameters()));
522             connect(wpval->end_right, SIGNAL(clicked()), this, SLOT(collectAllParameters()));
523             connect(wpval->end_center, SIGNAL(clicked()), this, SLOT(collectAllParameters()));
524             connect(wpval->start_up, SIGNAL(clicked()), this, SLOT(collectAllParameters()));
525             connect(wpval->start_down, SIGNAL(clicked()), this, SLOT(collectAllParameters()));
526             connect(wpval->start_left, SIGNAL(clicked()), this, SLOT(collectAllParameters()));
527             connect(wpval->start_right, SIGNAL(clicked()), this, SLOT(collectAllParameters()));
528             connect(wpval->start_center, SIGNAL(clicked()), this, SLOT(collectAllParameters()));
529             connect(wpval->start_transp, SIGNAL(valueChanged(int)), this, SLOT(collectAllParameters()));
530             connect(wpval->end_transp, SIGNAL(valueChanged(int)), this, SLOT(collectAllParameters()));
531             //wpval->title->setTitle(na.toElement().text());
532             m_uiItems.append(wpval);
533         } else if (type == "url") {
534             Urlval *cval = new Urlval;
535             QWidget * toFillin = new QWidget(m_baseWidget);
536             cval->setupUi(toFillin);
537             m_vbox->addWidget(toFillin);
538             cval->label->setText(paramName);
539             cval->urlwidget->fileDialog()->setFilter(ProjectList::getExtensions());
540             m_valueItems[paramName] = cval;
541             cval->urlwidget->setUrl(KUrl(value));
542             connect(cval->urlwidget, SIGNAL(returnPressed()) , this, SLOT(collectAllParameters()));
543             connect(cval->urlwidget, SIGNAL(urlSelected(const KUrl&)) , this, SLOT(collectAllParameters()));
544             m_uiItems.append(cval);
545         } else if (type == "keywords") {
546             Keywordval* kval = new Keywordval;
547             QWidget * toFillin = new QWidget(m_baseWidget);
548             kval->setupUi(toFillin);
549             m_vbox->addWidget(toFillin);
550             kval->label->setText(paramName);
551             kval->lineeditwidget->setText(value);
552             QDomElement klistelem = pa.firstChildElement("keywords");
553             QDomElement kdisplaylistelem = pa.firstChildElement("keywordsdisplay");
554             QStringList keywordlist;
555             QStringList keyworddisplaylist;
556             if (!klistelem.isNull()) {
557                 keywordlist = klistelem.text().split(';');
558                 keyworddisplaylist = i18n(kdisplaylistelem.text().toUtf8().data()).split(';');
559             }
560             if (keyworddisplaylist.count() != keywordlist.count()) {
561                 keyworddisplaylist = keywordlist;
562             }
563             for (int i = 0; i < keywordlist.count(); i++) {
564                 kval->comboboxwidget->addItem(keyworddisplaylist.at(i), keywordlist.at(i));
565             }
566             // Add disabled user prompt at index 0
567             kval->comboboxwidget->insertItem(0, i18n("<select a keyword>"), "");
568             kval->comboboxwidget->model()->setData( kval->comboboxwidget->model()->index(0,0), QVariant(Qt::NoItemFlags), Qt::UserRole -1);
569             kval->comboboxwidget->setCurrentIndex(0);
570             m_valueItems[paramName] = kval;
571             connect(kval->lineeditwidget, SIGNAL(editingFinished()) , this, SLOT(collectAllParameters()));
572             connect(kval->comboboxwidget, SIGNAL(activated (const QString&)), this, SLOT(collectAllParameters()));
573             m_uiItems.append(kval);
574         } else if (type == "fontfamily") {
575             Fontval* fval = new Fontval;
576             QWidget * toFillin = new QWidget(m_baseWidget);
577             fval->setupUi(toFillin);
578             m_vbox->addWidget(toFillin);
579             fval->name->setText(paramName);
580             fval->fontfamilywidget->setCurrentFont(QFont(value));
581             m_valueItems[paramName] = fval;
582             connect(fval->fontfamilywidget, SIGNAL(currentFontChanged(const QFont &)), this, SLOT(collectAllParameters())) ;
583             m_uiItems.append(fval);
584         } else if (type == "filterjob") {
585             QPushButton *button = new QPushButton(paramName, m_baseWidget);
586             m_vbox->addWidget(button);
587             m_valueItems[paramName] = button;
588             connect(button, SIGNAL(pressed()), this, SLOT(slotStartFilterJobAction()));   
589         }
590     }
591
592     if (stretch)
593         m_vbox->addStretch();
594
595     if (m_keyframeEditor)
596         m_keyframeEditor->checkVisibleParam();
597     
598     // Make sure all doubleparam spinboxes have the same width, looks much better
599     QList<DoubleParameterWidget *> allWidgets = findChildren<DoubleParameterWidget *>();
600     int minSize = 0;
601     for (int i = 0; i < allWidgets.count(); i++) {
602         if (minSize < allWidgets.at(i)->spinSize()) minSize = allWidgets.at(i)->spinSize();
603     }
604     for (int i = 0; i < allWidgets.count(); i++) {
605         allWidgets.at(i)->setSpinSize(minSize);
606     }*/
607 }
608
609 void EffectStackEdit::collectAllParameters()
610 {
611   /*
612     if (m_valueItems.isEmpty() || m_params.isNull()) return;
613     const QDomElement oldparam = m_params.cloneNode().toElement();
614     QDomElement newparam = oldparam.cloneNode().toElement();
615     QDomNodeList namenode = newparam.elementsByTagName("parameter");
616     QLocale locale;
617
618     for (int i = 0; i < namenode.count() ; i++) {
619         QDomNode pa = namenode.item(i);
620         QDomElement na = pa.firstChildElement("name");
621         QString type = pa.attributes().namedItem("type").nodeValue();
622         QString paramName = na.isNull() ? pa.attributes().namedItem("name").nodeValue() : i18n(na.text().toUtf8().data());
623         if (type == "complex")
624             paramName.append("complex");
625         else if (type == "position")
626             paramName.append("position");
627         else if (type == "geometry")
628             paramName.append("geometry");
629         else if (type == "keyframe")
630             paramName.append("keyframe");
631         if (type != "simplekeyframe" && type != "fixed" && type != "addedgeometry" && !m_valueItems.contains(paramName)) {
632             kDebug() << "// Param: " << paramName << " NOT FOUND";
633             continue;
634         }
635
636         QString setValue;
637         if (type == "double" || type == "constant") {
638             DoubleParameterWidget *doubleparam = (DoubleParameterWidget*)m_valueItems.value(paramName);
639             setValue = locale.toString(doubleparam->getValue());
640         } else if (type == "list") {
641             KComboBox *box = ((Listval*)m_valueItems.value(paramName))->list;
642             setValue = box->itemData(box->currentIndex()).toString();
643         } else if (type == "bool") {
644             QCheckBox *box = ((Boolval*)m_valueItems.value(paramName))->checkBox;
645             setValue = box->checkState() == Qt::Checked ? "1" : "0" ;
646         } else if (type == "color") {
647             ChooseColorWidget *choosecolor = ((ChooseColorWidget*)m_valueItems.value(paramName));
648             setValue = choosecolor->getColor();
649         } else if (type == "complex") {
650             ComplexParameter *complex = ((ComplexParameter*)m_valueItems.value(paramName));
651             namenode.item(i) = complex->getParamDesc();
652         } else if (type == "geometry") {
653             if (KdenliveSettings::on_monitor_effects()) {
654                 if (m_geometryWidget) namenode.item(i).toElement().setAttribute("value", m_geometryWidget->getValue());
655             } else {
656                 Geometryval *geom = ((Geometryval*)m_valueItems.value(paramName));
657                 namenode.item(i).toElement().setAttribute("value", geom->getValue());
658             }
659         } else if (type == "addedgeometry") {
660             namenode.item(i).toElement().setAttribute("value", m_geometryWidget->getExtraValue(namenode.item(i).toElement().attribute("name")));
661         } else if (type == "position") {
662             PositionEdit *pedit = ((PositionEdit*)m_valueItems.value(paramName));
663             int pos = pedit->getPosition();
664             setValue = QString::number(pos);
665             if (newparam.attribute("id") == "fadein" || newparam.attribute("id") == "fade_from_black") {
666                 // Make sure duration is not longer than clip
667
668                 EffectsList::setParameter(newparam, "in", QString::number(m_in));
669                 EffectsList::setParameter(newparam, "out", QString::number(m_in + pos));
670                 setValue.clear();
671             } else if (newparam.attribute("id") == "fadeout" || newparam.attribute("id") == "fade_to_black") {
672                 // Make sure duration is not longer than clip
673
674                 EffectsList::setParameter(newparam, "in", QString::number(m_out - pos));
675                 EffectsList::setParameter(newparam, "out", QString::number(m_out));
676                 setValue.clear();
677             }
678         } else if (type == "curve") {
679             KisCurveWidget *curve = ((KisCurveWidget*)m_valueItems.value(paramName));
680             QList<QPointF> points = curve->curve().points();
681             QString number = pa.attributes().namedItem("number").nodeValue();
682             QString inName = pa.attributes().namedItem("inpoints").nodeValue();
683             QString outName = pa.attributes().namedItem("outpoints").nodeValue();
684             int off = pa.attributes().namedItem("min").nodeValue().toInt();
685             int end = pa.attributes().namedItem("max").nodeValue().toInt();
686             if (oldparam.attribute("version").toDouble() > 0.2) {
687                 EffectsList::setParameter(newparam, number, locale.toString(points.count() / 10.));
688             } else {
689                 EffectsList::setParameter(newparam, number, QString::number(points.count()));
690             }
691             for (int j = 0; (j < points.count() && j + off <= end); j++) {
692                 QString in = inName;
693                 in.replace("%i", QString::number(j + off));
694                 QString out = outName;
695                 out.replace("%i", QString::number(j + off));
696                 EffectsList::setParameter(newparam, in, locale.toString(points.at(j).x()));
697                 EffectsList::setParameter(newparam, out, locale.toString(points.at(j).y()));
698             }
699             QString depends = pa.attributes().namedItem("depends").nodeValue();
700             if (!depends.isEmpty())
701                 meetDependency(paramName, type, EffectsList::parameter(newparam, depends));
702         } else if (type == "bezier_spline") {
703             BezierSplineWidget *widget = (BezierSplineWidget*)m_valueItems.value(paramName);
704             setValue = widget->spline();
705             QString depends = pa.attributes().namedItem("depends").nodeValue();
706             if (!depends.isEmpty())
707                 meetDependency(paramName, type, EffectsList::parameter(newparam, depends));
708 #ifdef USE_QJSON
709         } else if (type == "roto-spline") {
710             RotoWidget *widget = static_cast<RotoWidget *>(m_valueItems.value(paramName));
711             setValue = widget->getSpline();
712 #endif
713         } else if (type == "wipe") {
714             Wipeval *wp = (Wipeval*)m_valueItems.value(paramName);
715             wipeInfo info;
716             if (wp->start_left->isChecked())
717                 info.start = LEFT;
718             else if (wp->start_right->isChecked())
719                 info.start = RIGHT;
720             else if (wp->start_up->isChecked())
721                 info.start = UP;
722             else if (wp->start_down->isChecked())
723                 info.start = DOWN;
724             else if (wp->start_center->isChecked())
725                 info.start = CENTER;
726             else
727                 info.start = LEFT;
728             info.startTransparency = wp->start_transp->value();
729
730             if (wp->end_left->isChecked())
731                 info.end = LEFT;
732             else if (wp->end_right->isChecked())
733                 info.end = RIGHT;
734             else if (wp->end_up->isChecked())
735                 info.end = UP;
736             else if (wp->end_down->isChecked())
737                 info.end = DOWN;
738             else if (wp->end_center->isChecked())
739                 info.end = CENTER;
740             else
741                 info.end = RIGHT;
742             info.endTransparency = wp->end_transp->value();
743
744             setValue = getWipeString(info);
745         } else if ((type == "simplekeyframe" || type == "keyframe") && m_keyframeEditor) {
746             QDomElement elem = pa.toElement();
747             QString realName = i18n(na.toElement().text().toUtf8().data());
748             QString val = m_keyframeEditor->getValue(realName);
749             elem.setAttribute("keyframes", val);
750
751             if (m_keyframeEditor->isVisibleParam(realName))
752                 elem.setAttribute("intimeline", "1");
753             else if (elem.hasAttribute("intimeline"))
754                 elem.removeAttribute("intimeline");
755         } else if (type == "url") {
756             KUrlRequester *req = ((Urlval*)m_valueItems.value(paramName))->urlwidget;
757             setValue = req->url().path();
758         } else if (type == "keywords"){
759             QLineEdit *line = ((Keywordval*)m_valueItems.value(paramName))->lineeditwidget;
760             QComboBox *combo = ((Keywordval*)m_valueItems.value(paramName))->comboboxwidget;
761             if(combo->currentIndex())
762             {
763                 QString comboval = combo->itemData(combo->currentIndex()).toString();
764                 line->insert(comboval);
765                 combo->setCurrentIndex(0);
766             }
767             setValue = line->text();
768         } else if (type == "fontfamily") {
769             QFontComboBox* fontfamily = ((Fontval*)m_valueItems.value(paramName))->fontfamilywidget;
770             setValue = fontfamily->currentFont().family();
771         }
772
773         if (!setValue.isNull())
774             pa.attributes().namedItem("value").setNodeValue(setValue);
775
776     }
777     emit parameterChanged(oldparam, newparam);*/
778 }
779
780 void EffectStackEdit::clearAllItems()
781 {
782     blockSignals(true);
783     m_valueItems.clear();
784     m_uiItems.clear();
785     /*while (!m_items.isEmpty()) {
786         QWidget *die = m_items.takeFirst();
787         die->disconnect();
788         delete die;
789     }*/
790     //qDeleteAll(m_uiItems);
791     QLayoutItem *child;
792     while ((child = m_vbox->takeAt(0)) != 0) {
793         QWidget *wid = child->widget();
794         delete child;
795         if (wid) delete wid;
796     }
797     m_keyframeEditor = NULL;
798     m_geometryWidget = NULL;
799     blockSignals(false);
800 }
801
802 void EffectStackEdit::slotSyncEffectsPos(int pos)
803 {
804     emit syncEffectsPos(pos);
805 }
806
807 void EffectStackEdit::slotStartFilterJobAction()
808 {
809     QDomNodeList namenode = m_params.elementsByTagName("parameter");
810     for (int i = 0; i < namenode.count() ; i++) {
811         QDomElement pa = namenode.item(i).toElement();
812         QString type = pa.attribute("type");
813         if (type == "filterjob") {
814             emit startFilterJob(pa.attribute("filtertag"), pa.attribute("filterparams"), pa.attribute("finalfilter"), pa.attribute("consumer"), pa.attribute("consumerparams"), pa.attribute("wantedproperties"));
815             kDebug()<<" - - -PROPS:\n"<<pa.attribute("filtertag")<<"-"<< pa.attribute("filterparams")<<"-"<< pa.attribute("consumer")<<"-"<< pa.attribute("consumerparams")<<"-"<< pa.attribute("wantedproperties");
816             break;
817         }
818     }
819 }
820
821