]> git.sesse.net Git - kdenlive/blob - src/geometryval.cpp
037b4ebdb54f3164267219e21810f2883c19c4d7
[kdenlive] / src / geometryval.cpp
1 /***************************************************************************
2                           geomeytrval.cpp  -  description
3                              -------------------
4     begin                : 03 Aug 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 "geometryval.h"
19 #include "graphicsscenerectmove.h"
20 #include "kdenlivesettings.h"
21
22 #include <KDebug>
23
24 #include <QGraphicsView>
25 #include <QVBoxLayout>
26 #include <QGraphicsRectItem>
27 #include <QMenu>
28 #include <QInputDialog>
29
30
31 Geometryval::Geometryval(const MltVideoProfile profile, Timecode t, QPoint frame_size, int startPoint, QWidget* parent) :
32         QWidget(parent),
33         m_profile(profile),
34         m_timecode(t),
35         m_paramRect(NULL),
36         m_geom(NULL),
37         m_path(NULL),
38         m_fixedMode(false),
39         m_frameSize(frame_size),
40         m_startPoint(startPoint)
41 {
42     setupUi(this);
43     QVBoxLayout* vbox = new QVBoxLayout(widget);
44     m_sceneview = new QGraphicsView(this);
45     m_sceneview->setBackgroundBrush(QBrush(Qt::black));
46     vbox->addWidget(m_sceneview);
47     vbox->setContentsMargins(0, 0, 0, 0);
48
49     QVBoxLayout* vbox2 = new QVBoxLayout(keyframeWidget);
50     m_helper = new KeyframeHelper(this);
51     vbox2->addWidget(m_helper);
52     vbox2->setContentsMargins(0, 0, 0, 0);
53
54     connect(m_helper, SIGNAL(positionChanged(int)), this, SLOT(slotPositionChanged(int)));
55     connect(m_helper, SIGNAL(keyframeMoved(int)), this, SLOT(slotKeyframeMoved(int)));
56     connect(m_helper, SIGNAL(addKeyframe(int)), this, SLOT(slotAddFrame(int)));
57     connect(m_helper, SIGNAL(removeKeyframe(int)), this, SLOT(slotDeleteFrame(int)));
58
59     m_scene = new GraphicsSceneRectMove(this);
60     m_scene->setTool(TITLE_SELECT);
61     m_sceneview->setScene(m_scene);
62     m_dar = (m_profile.height * m_profile.display_aspect_num / (double) m_profile.display_aspect_den) / (double) m_profile.width;
63
64     m_realWidth = (int)(profile.height * profile.display_aspect_num / (double) profile.display_aspect_den);
65     QGraphicsRectItem *frameBorder = new QGraphicsRectItem(QRectF(0, 0, m_realWidth, profile.height));
66     frameBorder->setZValue(-1100);
67     frameBorder->setBrush(QColor(255, 255, 0, 30));
68     frameBorder->setPen(QPen(QBrush(QColor(255, 255, 255, 255)), 1.0, Qt::DashLine));
69     m_scene->addItem(frameBorder);
70
71     buttonNext->setIcon(KIcon("media-skip-forward"));
72     buttonNext->setToolTip(i18n("Go to next keyframe"));
73     buttonPrevious->setIcon(KIcon("media-skip-backward"));
74     buttonPrevious->setToolTip(i18n("Go to previous keyframe"));
75     buttonAdd->setIcon(KIcon("document-new"));
76     buttonAdd->setToolTip(i18n("Add keyframe"));
77     buttonDelete->setIcon(KIcon("edit-delete"));
78     buttonDelete->setToolTip(i18n("Delete keyframe"));
79
80     m_configMenu = new QMenu(i18n("Misc..."), this);
81     buttonMenu->setMenu(m_configMenu);
82     buttonMenu->setPopupMode(QToolButton::MenuButtonPopup);
83
84     m_editOptions = m_configMenu->addAction(KIcon("system-run"), i18n("Show/Hide options"));
85     m_editOptions->setCheckable(true);
86     buttonMenu->setDefaultAction(m_editOptions);
87     connect(m_editOptions, SIGNAL(triggered()), this, SLOT(slotSwitchOptions()));
88     slotSwitchOptions();
89
90     m_reset = m_configMenu->addAction(KIcon("view-refresh"), i18n("Reset"), this, SLOT(slotResetPosition()));
91
92     m_syncAction = m_configMenu->addAction(i18n("Sync timeline cursor"), this, SLOT(slotSyncCursor()));
93     m_syncAction->setCheckable(true);
94     m_syncAction->setChecked(KdenliveSettings::transitionfollowcursor());
95
96     //scene->setSceneRect(0, 0, profile.width * 2, profile.height * 2);
97     //view->fitInView(m_frameBorder, Qt::KeepAspectRatio);
98     const double sc = 100.0 / profile.height * 0.8;
99     QRectF srect = m_sceneview->sceneRect();
100     m_sceneview->setSceneRect(srect.x(), -srect.height() / 3 + 10, srect.width(), srect.height() + srect.height() / 3 * 2 - 10);
101     m_scene->setZoom(sc);
102     m_sceneview->centerOn(frameBorder);
103     m_sceneview->setMouseTracking(true);
104     connect(buttonNext , SIGNAL(clicked()) , this , SLOT(slotNextFrame()));
105     connect(buttonPrevious , SIGNAL(clicked()) , this , SLOT(slotPreviousFrame()));
106     connect(buttonDelete , SIGNAL(clicked()) , this , SLOT(slotDeleteFrame()));
107     connect(buttonAdd , SIGNAL(clicked()) , this , SLOT(slotAddFrame()));
108     connect(m_scene, SIGNAL(actionFinished()), this, SLOT(slotUpdateTransitionProperties()));
109     connect(m_scene, SIGNAL(doubleClickEvent()), this, SLOT(slotGeometry()));
110     connect(pos_up, SIGNAL(clicked()), this, SLOT(slotPosUp()));
111     connect(pos_down, SIGNAL(clicked()), this, SLOT(slotPosDown()));
112
113     buttonhcenter->setIcon(KIcon("kdenlive-align-hor"));
114     buttonhcenter->setToolTip(i18n("Align item horizontally"));
115     buttonvcenter->setIcon(KIcon("kdenlive-align-vert"));
116     buttonvcenter->setToolTip(i18n("Align item vertically"));
117     buttontop->setIcon(KIcon("kdenlive-align-top"));
118     buttontop->setToolTip(i18n("Align item to top"));
119     buttonbottom->setIcon(KIcon("kdenlive-align-bottom"));
120     buttonbottom->setToolTip(i18n("Align item to bottom"));
121     buttonright->setIcon(KIcon("kdenlive-align-right"));
122     buttonright->setToolTip(i18n("Align item to right"));
123     buttonleft->setIcon(KIcon("kdenlive-align-left"));
124     buttonleft->setToolTip(i18n("Align item to left"));
125
126     connect(buttonhcenter, SIGNAL(clicked()), this, SLOT(slotAlignHCenter()));
127     connect(buttonvcenter, SIGNAL(clicked()), this, SLOT(slotAlignVCenter()));
128     connect(buttontop, SIGNAL(clicked()), this, SLOT(slotAlignTop()));
129     connect(buttonbottom, SIGNAL(clicked()), this, SLOT(slotAlignBottom()));
130     connect(buttonright, SIGNAL(clicked()), this, SLOT(slotAlignRight()));
131     connect(buttonleft, SIGNAL(clicked()), this, SLOT(slotAlignLeft()));
132     connect(spinX, SIGNAL(valueChanged(int)), this, SLOT(slotGeometryX(int)));
133     connect(spinY, SIGNAL(valueChanged(int)), this, SLOT(slotGeometryY(int)));
134     connect(spinWidth, SIGNAL(valueChanged(int)), this, SLOT(slotGeometryWidth(int)));
135     connect(spinHeight, SIGNAL(valueChanged(int)), this, SLOT(slotGeometryHeight(int)));
136     connect(spinResize, SIGNAL(editingFinished()), this, SLOT(slotResizeCustom()));
137     connect(buttonResize, SIGNAL(clicked()), this, SLOT(slotResizeOriginal()));
138
139     connect(this, SIGNAL(parameterChanged()), this, SLOT(slotUpdateGeometry()));
140 }
141
142
143 Geometryval::~Geometryval()
144 {
145     m_scene->disconnect();
146     delete m_syncAction;
147     delete m_configMenu;
148     delete m_paramRect;
149     delete m_path;
150     delete m_helper;
151     delete m_geom;
152     delete m_sceneview;
153     delete m_scene;
154 }
155
156
157 void Geometryval::slotAlignHCenter()
158 {
159     if (!keyframeSelected())
160         return;
161     m_paramRect->setPos((m_realWidth - m_paramRect->rect().width()) / 2, m_paramRect->pos().y());
162     slotUpdateTransitionProperties();
163 }
164
165 void Geometryval::slotAlignVCenter()
166 {
167     if (!keyframeSelected())
168         return;
169     m_paramRect->setPos(m_paramRect->pos().x(), (m_profile.height - m_paramRect->rect().height()) / 2);
170     slotUpdateTransitionProperties();
171 }
172
173 void Geometryval::slotAlignTop()
174 {
175     if (!keyframeSelected())
176         return;
177     m_paramRect->setPos(m_paramRect->pos().x(), 0);
178     slotUpdateTransitionProperties();
179 }
180
181 void Geometryval::slotAlignBottom()
182 {
183     if (!keyframeSelected())
184         return;
185     m_paramRect->setPos(m_paramRect->pos().x(), m_profile.height - m_paramRect->rect().height());
186     slotUpdateTransitionProperties();
187 }
188
189 void Geometryval::slotAlignLeft()
190 {
191     if (!keyframeSelected())
192         return;
193     m_paramRect->setPos(0, m_paramRect->pos().y());
194     slotUpdateTransitionProperties();
195 }
196
197 void Geometryval::slotAlignRight()
198 {
199     if (!keyframeSelected())
200         return;
201     m_paramRect->setPos(m_realWidth - m_paramRect->rect().width(), m_paramRect->pos().y());
202     slotUpdateTransitionProperties();
203 }
204
205 void Geometryval::slotResizeOriginal()
206 {
207     if (!keyframeSelected())
208         return;
209     if (m_frameSize.isNull())
210         m_paramRect->setRect(0, 0, m_realWidth, m_profile.height);
211     else
212         m_paramRect->setRect(0, 0, m_frameSize.x(), m_frameSize.y());
213     slotUpdateTransitionProperties();
214 }
215
216 void Geometryval::slotResizeCustom()
217 {
218     if (!keyframeSelected())
219         return;
220     int value = spinResize->value();
221     m_paramRect->setRect(0, 0, m_realWidth * value / 100, m_profile.height * value / 100);
222     slotUpdateTransitionProperties();
223 }
224
225 void Geometryval::slotTransparencyChanged(int transp)
226 {
227     int pos;
228     if (KdenliveSettings::frametimecode()) pos = timePos->text().toInt();
229     else pos = m_timecode.getFrameCount(timePos->text());
230     Mlt::GeometryItem item;
231     int error = m_geom->fetch(&item, pos);
232     if (error || item.key() == false) {
233         // no keyframe under cursor
234         return;
235     }
236     item.mix(transp);
237     m_paramRect->setBrush(QColor(255, 0, 0, transp));
238     m_geom->insert(item);
239     emit parameterChanged();
240 }
241
242 void Geometryval::slotSyncCursor()
243 {
244     KdenliveSettings::setTransitionfollowcursor(m_syncAction->isChecked());
245 }
246
247 void Geometryval::updateTimecodeFormat()
248 {
249     timePos->setInputMask("");
250     if (KdenliveSettings::frametimecode()) {
251         int frames = m_timecode.getFrameCount(timePos->text());
252         QIntValidator *valid = new QIntValidator(this);
253         valid->setBottom(0);
254         timePos->setValidator(valid);
255         timePos->setText(QString::number(frames));
256     } else {
257         int pos = timePos->text().toInt();
258         timePos->setValidator(m_timecode.validator());
259         timePos->setText(m_timecode.getTimecodeFromFrames(pos));
260     }
261 }
262
263 void Geometryval::slotPosUp()
264 {
265     int pos;
266     if (KdenliveSettings::frametimecode()) pos = timePos->text().toInt();
267     else pos = m_timecode.getFrameCount(timePos->text());
268     pos ++;
269     if (pos > m_helper->frameLength) pos = m_helper->frameLength;
270     if (KdenliveSettings::frametimecode()) {
271         timePos->setText(QString::number(pos));
272     } else timePos->setText(m_timecode.getTimecodeFromFrames(pos));
273     slotPositionChanged();
274 }
275
276 void Geometryval::slotPosDown()
277 {
278     int pos;
279     if (KdenliveSettings::frametimecode()) pos = timePos->text().toInt();
280     else pos = m_timecode.getFrameCount(timePos->text());
281     pos --;
282     if (pos < 0) pos = 0;
283     if (KdenliveSettings::frametimecode()) {
284         timePos->setText(QString::number(pos));
285     } else timePos->setText(m_timecode.getTimecodeFromFrames(pos));
286     slotPositionChanged();
287 }
288
289 void Geometryval::slotPositionChanged(int pos, bool seek)
290 {
291     if (pos == -1) {
292         if (KdenliveSettings::frametimecode()) pos = timePos->text().toInt();
293         else pos = m_timecode.getFrameCount(timePos->text());
294     }
295     if (seek && KdenliveSettings::transitionfollowcursor()) emit seekToPos(pos + m_startPoint);
296     if (KdenliveSettings::frametimecode()) {
297         timePos->setText(QString::number(pos));
298     } else timePos->setText(m_timecode.getTimecodeFromFrames(pos));
299
300     //spinPos->setValue(pos);
301     m_helper->setValue(pos);
302     Mlt::GeometryItem item;
303     int error = m_geom->fetch(&item, pos);
304     if (error || item.key() == false) {
305         // no keyframe under cursor, adjust buttons
306         buttonAdd->setEnabled(true);
307         buttonDelete->setEnabled(false);
308         widget->setEnabled(false);
309         spinTransp->setEnabled(false);
310         frameOptions->setEnabled(false);
311         m_reset->setEnabled(false);
312     } else {
313         buttonAdd->setEnabled(false);
314         buttonDelete->setEnabled(true);
315         widget->setEnabled(true);
316         spinTransp->setEnabled(true);
317         frameOptions->setEnabled(true);
318         m_reset->setEnabled(true);
319     }
320
321     m_paramRect->setPos(item.x() * m_dar, item.y());
322     m_paramRect->setRect(0, 0, item.w() * m_dar, item.h());
323     spinTransp->setValue(item.mix());
324     m_paramRect->setBrush(QColor(255, 0, 0, item.mix()));
325     slotUpdateGeometry();
326 }
327
328 void Geometryval::slotDeleteFrame(int pos)
329 {
330     // check there is more than one keyframe
331     Mlt::GeometryItem item;
332     int frame;
333     if (KdenliveSettings::frametimecode()) frame = timePos->text().toInt();
334     else frame = m_timecode.getFrameCount(timePos->text());
335
336     if (pos == -1) pos = frame;
337     int error = m_geom->next_key(&item, pos + 1);
338     if (error) {
339         error = m_geom->prev_key(&item, pos - 1);
340         if (error || item.frame() == pos) return;
341     }
342
343     m_geom->remove(frame);
344     buttonAdd->setEnabled(true);
345     buttonDelete->setEnabled(false);
346     widget->setEnabled(false);
347     spinTransp->setEnabled(false);
348     frameOptions->setEnabled(false);
349     m_reset->setEnabled(false);
350     m_helper->update();
351     slotPositionChanged(pos, false);
352     updateTransitionPath();
353     emit parameterChanged();
354 }
355
356 void Geometryval::slotAddFrame(int pos)
357 {
358     int frame;
359     if (KdenliveSettings::frametimecode()) frame = timePos->text().toInt();
360     else frame = m_timecode.getFrameCount(timePos->text());
361     if (pos == -1) pos = frame;
362     Mlt::GeometryItem item;
363     item.frame(pos);
364     QRectF r = m_paramRect->rect().normalized();
365     QPointF rectpos = m_paramRect->pos();
366     item.x(rectpos.x() / m_dar);
367     item.y(rectpos.y());
368     item.w(r.width() / m_dar);
369     item.h(r.height());
370     item.mix(spinTransp->value());
371     m_geom->insert(item);
372     buttonAdd->setEnabled(false);
373     buttonDelete->setEnabled(true);
374     widget->setEnabled(true);
375     spinTransp->setEnabled(true);
376     frameOptions->setEnabled(true);
377     m_reset->setEnabled(true);
378     m_helper->update();
379     emit parameterChanged();
380 }
381
382 void Geometryval::slotNextFrame()
383 {
384     Mlt::GeometryItem item;
385     int error = m_geom->next_key(&item, m_helper->value() + 1);
386     int pos;
387     kDebug() << "// SEEK TO NEXT KFR: " << error;
388     if (error) {
389         // Go to end
390         pos = m_helper->frameLength;
391     } else pos = item.frame();
392
393     if (KdenliveSettings::frametimecode()) {
394         timePos->setText(QString::number(pos));
395     } else timePos->setText(m_timecode.getTimecodeFromFrames(pos));
396     slotPositionChanged();
397 }
398
399 void Geometryval::slotPreviousFrame()
400 {
401     Mlt::GeometryItem item;
402     int error = m_geom->prev_key(&item, m_helper->value() - 1);
403     kDebug() << "// SEEK TO NEXT KFR: " << error;
404     if (error) return;
405     int pos = item.frame();
406     if (KdenliveSettings::frametimecode()) {
407         timePos->setText(QString::number(pos));
408     } else timePos->setText(m_timecode.getTimecodeFromFrames(pos));
409     slotPositionChanged();
410 }
411
412
413 QString Geometryval::getValue() const
414 {
415     return m_geom->serialise();
416 }
417
418 void Geometryval::setupParam(const QDomElement par, int minFrame, int maxFrame)
419 {
420     QString val = par.attribute("value");
421     if (par.attribute("fixed") == "1") {
422         m_fixedMode = true;
423         buttonPrevious->setHidden(true);
424         buttonNext->setHidden(true);
425         buttonDelete->setHidden(true);
426         buttonAdd->setHidden(true);
427         spinTransp->setMaximum(500);
428         label_pos->setHidden(true);
429         m_helper->setHidden(true);
430         timePos->setHidden(true);
431     }
432     if (par.attribute("opacity") == "false") {
433         label_opacity->setHidden(true);
434         spinTransp->setHidden(true);
435     } else if (par.attribute("opacity") == "nonzero") {
436         spinTransp->setMinimum(1);
437     }
438     char *tmp = (char *) qstrdup(val.toUtf8().data());
439     if (m_geom) m_geom->parse(tmp, maxFrame - minFrame, m_profile.width, m_profile.height);
440     else m_geom = new Mlt::Geometry(tmp, maxFrame - minFrame, m_profile.width, m_profile.height);
441     delete[] tmp;
442
443     //kDebug() << " / / UPDATING TRANSITION VALUE: " << m_geom->serialise();
444     //read param her and set rect
445     if (!m_fixedMode) {
446         m_helper->setKeyGeometry(m_geom, maxFrame - minFrame - 1);
447         m_helper->update();
448         /*QDomDocument doc;
449         doc.appendChild(doc.importNode(par, true));
450         kDebug() << "IMPORTED TRANS: " << doc.toString();*/
451         if (m_path == NULL) {
452             m_path = new QGraphicsPathItem();
453             m_path->setPen(QPen(Qt::red));
454             m_scene->addItem(m_path);
455         }
456         updateTransitionPath();
457     }
458     Mlt::GeometryItem item;
459
460     m_geom->fetch(&item, 0);
461     delete m_paramRect;
462     m_paramRect = new QGraphicsRectItem(QRectF(0, 0, item.w() * m_dar, item.h()));
463     m_paramRect->setPos(item.x() * m_dar, item.y());
464     m_paramRect->setZValue(0);
465     m_paramRect->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
466
467     m_paramRect->setPen(QPen(QBrush(QColor(255, 0, 0, 255)), 1.0));
468     m_scene->addItem(m_paramRect);
469     slotPositionChanged(0, false);
470     slotUpdateGeometry();
471     if (!m_fixedMode) {
472         connect(timePos, SIGNAL(editingFinished()), this , SLOT(slotPositionChanged()));
473     }
474     connect(spinTransp, SIGNAL(valueChanged(int)), this , SLOT(slotTransparencyChanged(int)));
475 }
476
477 void Geometryval::updateTransitionPath()
478 {
479     if (m_fixedMode) return;
480     Mlt::GeometryItem item;
481     int pos = 0;
482     int counter = 0;
483     QPainterPath path;
484     while (true) {
485         if (m_geom->next_key(&item, pos) == 1) break;
486         pos = item.frame();
487         if (counter == 0) {
488             path.moveTo(item.x() * m_dar + item.w() * m_dar / 2, item.y() + item.h() / 2);
489         } else {
490             path.lineTo(item.x() * m_dar + item.w() * m_dar / 2, item.y() + item.h() / 2);
491         }
492         counter++;
493         pos++;
494     }
495     m_path->setPath(path);
496 }
497
498 void Geometryval::slotUpdateTransitionProperties()
499 {
500     int pos;
501     if (KdenliveSettings::frametimecode()) pos = timePos->text().toInt();
502     else pos = m_timecode.getFrameCount(timePos->text());
503     Mlt::GeometryItem item;
504     int error = m_geom->next_key(&item, pos);
505     if (error || item.frame() != pos) {
506         // no keyframe under cursor
507         return;
508     }
509     QRectF r = m_paramRect->rect().normalized();
510     QPointF rectpos = m_paramRect->pos();
511     item.x(rectpos.x() / m_dar);
512     item.y(rectpos.y());
513     item.w(r.width() / m_dar);
514     item.h(r.height());
515     m_geom->insert(item);
516     updateTransitionPath();
517     emit parameterChanged();
518 }
519
520 void Geometryval::slotResetPosition()
521 {
522     spinX->setValue(0);
523     spinY->setValue(0);
524
525     if (m_frameSize.isNull()) {
526         spinWidth->setValue(m_realWidth);
527         spinHeight->setValue(m_profile.height);
528     } else {
529         spinWidth->setValue(m_frameSize.x());
530         spinHeight->setValue(m_frameSize.y());
531     }
532 }
533
534 void Geometryval::setFrameSize(QPoint p)
535 {
536     m_frameSize = p;
537 }
538
539
540 void Geometryval::slotKeyframeMoved(int pos)
541 {
542     slotPositionChanged(pos);
543     slotUpdateTransitionProperties();
544 }
545
546 void Geometryval::slotSwitchOptions()
547 {
548     if (frameOptions->isHidden()) {
549         frameOptions->setHidden(false);
550         m_editOptions->setChecked(true);
551     } else {
552         frameOptions->setHidden(true);
553         m_editOptions->setChecked(false);
554     }
555     //adjustSize();
556 }
557
558 void Geometryval::slotGeometryX(int value)
559 {
560     if (!keyframeSelected())
561         return;
562     m_paramRect->setPos(value, spinY->value());
563     slotUpdateTransitionProperties();
564 }
565
566 void Geometryval::slotGeometryY(int value)
567 {
568     if (!keyframeSelected())
569         return;
570     m_paramRect->setPos(spinX->value(), value);
571     slotUpdateTransitionProperties();
572 }
573
574 void Geometryval::slotGeometryWidth(int value)
575 {
576     if (!keyframeSelected())
577         return;
578     m_paramRect->setRect(0, 0, value, spinHeight->value());
579     slotUpdateTransitionProperties();
580 }
581
582 void Geometryval::slotGeometryHeight(int value)
583 {
584     if (!keyframeSelected())
585         return;
586     m_paramRect->setRect(0, 0, spinWidth->value(), value);
587     slotUpdateTransitionProperties();
588 }
589
590 void Geometryval::slotUpdateGeometry()
591 {
592     QRectF r = m_paramRect->rect().normalized();
593
594     spinX->blockSignals(true);
595     spinY->blockSignals(true);
596     spinWidth->blockSignals(true);
597     spinHeight->blockSignals(true);
598     spinResize->blockSignals(true);
599
600     spinX->setValue(m_paramRect->pos().x());
601     spinY->setValue(m_paramRect->pos().y());
602     spinWidth->setValue(r.width());
603     spinHeight->setValue(r.height());
604     spinResize->setValue(m_paramRect->rect().width() * 100 / m_realWidth);
605
606     spinX->blockSignals(false);
607     spinY->blockSignals(false);
608     spinWidth->blockSignals(false);
609     spinHeight->blockSignals(false);
610     spinResize->blockSignals(false);
611 }
612
613 bool Geometryval::keyframeSelected()
614 {
615     Mlt::GeometryItem item;
616     int pos;
617     if (KdenliveSettings::frametimecode()) pos = timePos->text().toInt();
618     else pos = m_timecode.getFrameCount(timePos->text());
619     if (m_geom->fetch(&item, pos) || item.key() == false) return false;
620     return true;
621 }
622
623
624