<description>Four corners geometry engine</description>
<author>Marko Cebokli</author>
- <!-- No actual parameter: Represents the corners widget (used to edit corners on the monitor) -->
- <parameter type="corners" default="0" xpoints="Corner %i X" ypoints="Corner %i Y" factor="6000">
- <name>Corners widget</name>
- </parameter>
-
- <parameter type="fixed" name="Corner 1 X" default="2000" min="0" max="6000" factor="6000">
+ <parameter type="simplekeyframe" widget="corners" name="Corner 1 X" default="2000" min="0" max="6000" factor="6000">
<name>Corner 1 X</name>
</parameter>
- <parameter type="fixed" name="Corner 1 Y" default="2000" min="0" max="6000" factor="6000">
+ <parameter type="simplekeyframe" widget="corners" name="Corner 1 Y" default="2000" min="0" max="6000" factor="6000">
<name>Corner 1 Y</name>
</parameter>
- <parameter type="fixed" name="Corner 2 X" default="4000" min="0" max="6000" factor="6000">
+ <parameter type="simplekeyframe" widget="corners" name="Corner 2 X" default="4000" min="0" max="6000" factor="6000">
<name>Corner 2 X</name>
</parameter>
- <parameter type="fixed" name="Corner 2 Y" default="2000" min="0" max="6000" factor="6000">
+ <parameter type="simplekeyframe" widget="corners" name="Corner 2 Y" default="2000" min="0" max="6000" factor="6000">
<name>Corner 2 Y</name>
</parameter>
- <parameter type="fixed" name="Corner 3 X" default="4000" min="0" max="6000" factor="6000">
+ <parameter type="simplekeyframe" widget="corners" name="Corner 3 X" default="4000" min="0" max="6000" factor="6000">
<name>Corner 3 X</name>
</parameter>
- <parameter type="fixed" name="Corner 3 Y" default="4000" min="0" max="6000" factor="6000">
+ <parameter type="simplekeyframe" widget="corners" name="Corner 3 Y" default="4000" min="0" max="6000" factor="6000">
<name>Corner 3 Y</name>
</parameter>
- <parameter type="fixed" name="Corner 4 X" default="2000" min="0" max="6000" factor="6000">
+ <parameter type="simplekeyframe" widget="corners" name="Corner 4 X" default="2000" min="0" max="6000" factor="6000">
<name>Corner 4 X</name>
</parameter>
- <parameter type="fixed" name="Corner 4 Y" default="4000" min="0" max="6000" factor="6000">
+ <parameter type="simplekeyframe" widget="corners" name="Corner 4 Y" default="4000" min="0" max="6000" factor="6000">
<name>Corner 4 Y</name>
</parameter>
+
+ <parameter type="simplekeyframe" widget="corners" name="Stretch X" default="1000" min="0" max="2000" factor="2000">
+ <name>Stretch X</name>
+ </parameter>
+
+ <parameter type="simplekeyframe" widget="corners" name="Stretch Y" default="1000" min="0" max="2000" factor="2000">
+ <name>Stretch Y</name>
+ </parameter>
+
+ <parameter type="simplekeyframe" widget="corners" name="Feather Alpha" default="5" min="0" max="100" factor="100">
+ <name>Feather Alpha</name>
+ </parameter>
<parameter type="bool" name="Enable Stretch" default="0">
<name>Enable Stretch</name>
</parameter>
-
- <parameter type="constant" name="Stretch X" default="1000" min="0" max="2000" factor="2000">
- <name>Stretch X</name>
- </parameter>
-
- <parameter type="constant" name="Stretch Y" default="1000" min="0" max="2000" factor="2000">
- <name>Stretch Y</name>
- </parameter>
-
<parameter type="list" name="Interpolator" default="0.166" paramlist="0,0.166,0.333,0.5,0.666,0.833,1.0">
<paramlistdisplay>Nearest neighbor,Bilinear,Bicubic smooth,Bicubic sharp,Spline 4x4,Spline 6x6,Lanczos</paramlistdisplay>
<name>Interpolator</name>
<name>Transparent Background</name>
</parameter>
- <parameter type="constant" name="Feather Alpha" default="5" min="0" max="100" factor="100">
- <name>Feather Alpha</name>
- </parameter>
+
</effect>
#include "kdenlivesettings.h"
#include <QGraphicsView>
-#include <QHBoxLayout>
+#include <QGridLayout>
#include <KIcon>
-CornersWidget::CornersWidget(Monitor* monitor, int clipPos, bool isEffect, int factor, QWidget* parent) :
- QWidget(parent),
+CornersWidget::CornersWidget(Monitor *monitor, QDomElement e, int minFrame, int maxFrame, Timecode tc, int activeKeyframe, QWidget* parent) :
+ KeyframeEdit(e, minFrame, maxFrame, tc, activeKeyframe, parent),
m_monitor(monitor),
- m_clipPos(clipPos),
- m_inPoint(0),
- m_outPoint(1),
- m_isEffect(isEffect),
- m_showScene(true),
- m_factor(factor)
+ m_showScene(true)
{
- m_ui.setupUi(this);
-
m_scene = monitor->getEffectScene();
m_item = new OnMonitorCornersItem(m_scene);
m_scene->addItem(m_item);
- m_config = new MonitorSceneControlWidget(m_scene, m_ui.frameConfig);
- QHBoxLayout *layout = new QHBoxLayout(m_ui.frameConfig);
- layout->setContentsMargins(0, 0, 0, 0);
- layout->addWidget(m_config);
- QHBoxLayout *layout2 = new QHBoxLayout(m_ui.widgetConfigButton);
- layout2->setContentsMargins(0, 0, 0, 0);
- layout2->addWidget(m_config->getShowHideButton());
+ m_config = new MonitorSceneControlWidget(m_scene, this);
+ QGridLayout *l = static_cast<QGridLayout *>(layout());
+ l->addWidget(m_config->getShowHideButton(), 1, 1);
+ l->addWidget(m_config, 1, 2);
QToolButton *buttonShowLines = new QToolButton(m_config);
// TODO: Better Icons
connect(buttonShowControls, SIGNAL(toggled(bool)), this, SLOT(slotShowControls(bool)));
m_config->addWidget(buttonShowControls, 0, 3);
- int width = m_monitor->render->frameRenderWidth();
- int height = m_monitor->render->renderHeight();
-
- m_ui.spinX1->setRange(-width, width * 2);
- m_ui.spinX2->setRange(-width, width * 2);
- m_ui.spinX3->setRange(-width, width * 2);
- m_ui.spinX4->setRange(-width, width * 2);
- m_ui.spinY1->setRange(-height, height * 2);
- m_ui.spinY2->setRange(-height, height * 2);
- m_ui.spinY3->setRange(-height, height * 2);
- m_ui.spinY4->setRange(-height, height * 2);
-
- m_ui.toolReset1->setIcon(KIcon("edit-undo"));
- m_ui.toolReset1->setToolTip(i18n("Reset Corner 1"));
- m_ui.toolReset2->setIcon(KIcon("edit-undo"));
- m_ui.toolReset2->setToolTip(i18n("Reset Corner 2"));
- m_ui.toolReset3->setIcon(KIcon("edit-undo"));
- m_ui.toolReset3->setToolTip(i18n("Reset Corner 3"));
- m_ui.toolReset4->setIcon(KIcon("edit-undo"));
- m_ui.toolReset4->setToolTip(i18n("Reset Corner 4"));
-
- connect(m_ui.spinX1, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem()));
- connect(m_ui.spinX2, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem()));
- connect(m_ui.spinX3, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem()));
- connect(m_ui.spinX4, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem()));
- connect(m_ui.spinY1, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem()));
- connect(m_ui.spinY2, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem()));
- connect(m_ui.spinY3, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem()));
- connect(m_ui.spinY4, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem()));
-
- connect(m_ui.toolReset1, SIGNAL(clicked()), this, SLOT(slotResetCorner1()));
- connect(m_ui.toolReset2, SIGNAL(clicked()), this, SLOT(slotResetCorner2()));
- connect(m_ui.toolReset3, SIGNAL(clicked()), this, SLOT(slotResetCorner3()));
- connect(m_ui.toolReset4, SIGNAL(clicked()), this, SLOT(slotResetCorner4()));
-
connect(m_config, SIGNAL(showScene(bool)), this, SLOT(slotShowScene(bool)));
connect(m_monitor, SIGNAL(renderPosition(int)), this, SLOT(slotCheckMonitorPosition(int)));
connect(m_scene, SIGNAL(actionFinished()), this, SLOT(slotUpdateProperties()));
+
+ connect(keyframe_list, SIGNAL(itemSelectionChanged()), this, SLOT(slotUpdateItem()));
+ connect(keyframe_list, SIGNAL(cellChanged(int, int)), this, SLOT(slotUpdateItem()));
}
CornersWidget::~CornersWidget()
m_monitor->slotEffectScene(false);
}
-void CornersWidget::setRange(int minframe, int maxframe)
-{
- m_inPoint = minframe;
- m_outPoint = maxframe;
- slotCheckMonitorPosition(m_monitor->render->seekFramePosition());
-}
-
void CornersWidget::slotUpdateItem()
{
- QPointF c1(m_ui.spinX1->value(), m_ui.spinY1->value());
- QPointF c2(m_ui.spinX2->value(), m_ui.spinY2->value());
- QPointF c3(m_ui.spinX3->value(), m_ui.spinY3->value());
- QPointF c4(m_ui.spinX4->value(), m_ui.spinY4->value());
-
- m_item->setPolygon(QPolygonF() << c1 << c2 << c3 << c4);
-
- emit parameterChanged();
-}
-
-void CornersWidget::slotUpdateProperties(bool changed)
-{
- QPolygon pol = m_item->polygon().toPolygon();
- blockSignals(true);
- m_ui.spinX1->setValue(pol.at(0).x());
- m_ui.spinX2->setValue(pol.at(1).x());
- m_ui.spinX3->setValue(pol.at(2).x());
- m_ui.spinX4->setValue(pol.at(3).x());
- m_ui.spinY1->setValue(pol.at(0).y());
- m_ui.spinY2->setValue(pol.at(1).y());
- m_ui.spinY3->setValue(pol.at(2).y());
- m_ui.spinY4->setValue(pol.at(3).y());
- blockSignals(false);
+ QList<QPointF> points;
+
+ QTableWidgetItem *item = keyframe_list->currentItem();
+ if (!item || keyframe_list->columnCount() < 8)
+ return;
+
+ double val;
+ for (int col = 0; col < 8; col++) {
+ if (!keyframe_list->item(item->row(), col))
+ return;
+ val = (keyframe_list->item(item->row(), col)->text().toInt() - 2000) / 2000.;
+ if (col % 2 == 0)
+ points << QPointF(val * m_monitor->render->frameRenderWidth(), 0);
+ else
+ points[col / 2].setY(val * m_monitor->render->renderHeight());
+ }
- if (changed)
- emit parameterChanged();
+ m_scene->blockSignals(true);
+ m_item->setPolygon(QPolygonF() << points.at(0) << points.at(1) << points.at(2) << points.at(3));
+ m_scene->blockSignals(false);
}
-
-QPolygon CornersWidget::getValue()
+void CornersWidget::slotUpdateProperties()
{
- qreal width = m_monitor->render->frameRenderWidth();
- qreal height = m_monitor->render->renderHeight();
- QPolygon corners = m_item->polygon().toPolygon();
- QPolygon points;
- QPoint p;
- for (int i = 0; i < 4; ++i) {
- p = corners.at(i);
- p.setX((p.x() / width + 1) / 3.0 * m_factor);
- p.setY((p.y() / height + 1) / 3.0 * m_factor);
- points << p;
+ if (keyframe_list->columnCount() < 8)
+ return;
+
+ QPolygonF pol = m_item->polygon();
+
+ QTableWidgetItem *item = keyframe_list->currentItem();
+ double val;
+ for (int col = 0; col < 8; col++) {
+ if (col % 2 == 0)
+ val = pol.at(col / 2).x() / (double)m_monitor->render->frameRenderWidth();
+ else
+ val = pol.at(col / 2).y() / (double)m_monitor->render->renderHeight();
+ val *= 2000;
+ val += 2000;
+ QTableWidgetItem *nitem = keyframe_list->item(item->row(), col);
+ if (nitem->text().toInt() != (int)val)
+ nitem->setText(QString::number((int)val));
}
- return points;
-}
-void CornersWidget::setValue(const QPolygon& points)
-{
- int width = m_monitor->render->frameRenderWidth();
- int height = m_monitor->render->renderHeight();
- QPolygonF corners;
- QPoint p;
- for (int i = 0; i < 4; ++i) {
- p = points.at(i);
- p.setX((p.x() / (qreal)m_factor * 3 - 1) * width);
- p.setY((p.y() / (qreal)m_factor * 3 - 1) * height);
- corners << p;
- }
- m_item->setPolygon(corners);
+ slotAdjustKeyframeInfo(false);
- slotUpdateProperties(false);
+ if (changed)
+ emit parameterChanged();
}
void CornersWidget::slotCheckMonitorPosition(int renderPos)
{
- if (m_showScene) {
- /*
- We do only get the position in timeline if this geometry belongs to a transition,
- therefore we need two ways here.
- */
- if (m_isEffect) {
- emit checkMonitorPosition(renderPos);
- } else {
- if (renderPos >= m_clipPos && renderPos <= m_clipPos + m_outPoint - m_inPoint) {
- if (!m_scene->views().at(0)->isVisible())
- m_monitor->slotEffectScene(true);
- } else {
- m_monitor->slotEffectScene(false);
- }
- }
- }
+ if (m_showScene)
+ emit checkMonitorPosition(renderPos);
}
void CornersWidget::slotShowScene(bool show)
m_item->update();
}
-void CornersWidget::slotResetCorner1()
-{
- blockSignals(true);
- m_ui.spinX1->setValue(0);
- m_ui.spinY1->setValue(0);
- blockSignals(false);
- slotUpdateItem();
-}
-
-void CornersWidget::slotResetCorner2()
-{
- blockSignals(true);
- m_ui.spinX2->setValue(m_monitor->render->frameRenderWidth());
- m_ui.spinY2->setValue(0);
- blockSignals(false);
- slotUpdateItem();
-}
-
-void CornersWidget::slotResetCorner3()
-{
- blockSignals(true);
- m_ui.spinX3->setValue(m_monitor->render->frameRenderWidth());
- m_ui.spinY3->setValue(m_monitor->render->renderHeight());
- blockSignals(false);
- slotUpdateItem();
-}
-
-void CornersWidget::slotResetCorner4()
-{
- blockSignals(true);
- m_ui.spinX4->setValue(0);
- m_ui.spinY4->setValue(m_monitor->render->renderHeight());
- blockSignals(false);
- slotUpdateItem();
-}
-
#include "cornerswidget.moc"
#ifndef CORNERSWIDGET_H
#define CORNERSWIDGET_H
-#include "ui_cornerswidget_ui.h"
+#include "keyframeedit.h"
-#include <QWidget>
class QDomElement;
class Monitor;
class MonitorSceneControlWidget;
-class CornersWidget : public QWidget
+class CornersWidget : public KeyframeEdit
{
Q_OBJECT
public:
* @param isEffect true if used in an effect, false if used in a transition
* @param factor Factor by which the parameters differ from the range 0-1
* @param parent (optional) Parent widget */
- CornersWidget(Monitor *monitor, int clipPos, bool isEffect, int factor, QWidget* parent = 0);
+ CornersWidget(Monitor *monitor, QDomElement e, int minFrame, int maxFrame, Timecode tc, int activeKeyframe, QWidget* parent = 0);
virtual ~CornersWidget();
- /** @brief Returns a polygon representing the corners in the range 0 - factor. */
- QPolygon getValue();
-
- /** @brief Takes a polygon @param points in the range 0 - factor and converts it into range (- frame width|height) - (2*frame width|height). */
- void setValue(const QPolygon &points);
-
- /** @brief Takes in and outpoint of the clip to know when to show the on-monitor scene.
- * @param minframe In point of the clip
- * @param maxframe Out point of the clip */
- void setRange(int minframe, int maxframe);
-
public slots:
/** @brief Switches from normal monitor to monitor scene according to @param show. */
void slotShowScene(bool show = true);
private:
- Ui::CornersWidget_UI m_ui;
Monitor *m_monitor;
- /** Position of the clip in timeline. */
- int m_clipPos;
- /** In point of the clip (crop from start). */
- int m_inPoint;
- /** Out point of the clip (crop from end). */
- int m_outPoint;
- bool m_isEffect;
MonitorScene *m_scene;
OnMonitorCornersItem *m_item;
bool m_showScene;
MonitorSceneControlWidget *m_config;
- int m_factor;
private slots:
/** @brief Makes sure the monitor effect scene is only visible if the clip this geometry belongs to is visible.
* @param renderPos Postion of the Monitor / Timeline cursor */
void slotCheckMonitorPosition(int renderPos);
- /** @brief Updates the on-monitor item according to the spinboxes. */
+ /** @brief Updates the on-monitor item according current values in the keyframe editor. */
void slotUpdateItem();
- /** @brief Updates the spinboxes according to the on-monitor item.
- * @param changed (default = true) Whether to emit parameterChanged */
- void slotUpdateProperties(bool changed = true);
+ /** @brief Updates the keyframe editor according to the on-monitor item. */
+ void slotUpdateProperties();
/** @brief Shows/Hides the lines connecting the corners in the on-monitor item according to @param show. */
void slotShowLines(bool show = true);
+ /** @brief Shows/Hides additional controls on the monitor according to @param show. */
void slotShowControls(bool show = true);
- /*
- * These functions reset the positions of the corners.
- * The default values in the effect XML file are not considered, but
- * the position the corner would have without this effect applied.
- */
- void slotResetCorner1();
- void slotResetCorner2();
- void slotResetCorner3();
- void slotResetCorner4();
-
signals:
- void parameterChanged();
void checkMonitorPosition(int);
};
} else if (type == "keyframe" || type == "simplekeyframe") {
// keyframe editor widget
if (m_keyframeEditor == NULL) {
- KeyframeEdit *geo = new KeyframeEdit(pa, m_in, m_in + m_out, m_timecode, e.attribute("active_keyframe", "-1").toInt());
+ 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);
+ corners->slotShowScene(!disable);
+ connect(corners, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int)));
+ connect(this, SIGNAL(effectStateChanged(bool)), corners, SLOT(slotShowScene(bool)));
+ geo = static_cast<KeyframeEdit *>(corners);
+ } else {
+ geo = new KeyframeEdit(pa, m_in, m_in + m_out, m_timecode, e.attribute("active_keyframe", "-1").toInt());
+ }
m_vbox->addWidget(geo);
m_valueItems[paramName+"keyframe"] = geo;
m_keyframeEditor = geo;
QString depends = pa.attribute("depends");
if (!depends.isEmpty())
meetDependency(paramName, type, EffectsList::parameter(e, depends));
- } else if (type == "corners") {
- CornersWidget *corners = new CornersWidget(m_monitor, pos, isEffect, pa.attribute("factor").toInt(), this);
- corners->slotShowScene(!disable);
- connect(corners, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int)));
- if (minFrame == maxFrame)
- corners->setRange(m_in, m_out);
- else
- corners->setRange(minFrame, maxFrame);
-
- QString xName = pa.attribute("xpoints");
- QString yName = pa.attribute("ypoints");
- QPolygon points;
- int x, y;
- for (int j = 1; j <= 4; ++j) {
- x = EffectsList::parameter(e, QString(xName).replace("%i", QString::number(j))).toInt();
- y = EffectsList::parameter(e, QString(yName).replace("%i", QString::number(j))).toInt();
- points << QPoint(x, y);
- }
- corners->setValue(points);
- m_vbox->addWidget(corners);
- connect(corners, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters()));
- connect(this, SIGNAL(effectStateChanged(bool)), corners, SLOT(slotShowScene(bool)));
- m_valueItems[paramName] = corners;
} else if (type == "wipe") {
Wipeval *wpval = new Wipeval;
wpval->setupUi(toFillin);
QString depends = pa.attributes().namedItem("depends").nodeValue();
if (!depends.isEmpty())
meetDependency(paramName, type, EffectsList::parameter(newparam, depends));
- } else if (type == "corners") {
- CornersWidget *corners = ((CornersWidget*)m_valueItems.value(paramName));
- QString xName = pa.attributes().namedItem("xpoints").nodeValue();
- QString yName = pa.attributes().namedItem("ypoints").nodeValue();
- QPolygon points = corners->getValue();
- QPoint p;
- for (int j = 1; j <= 4; ++j) {
- p = points.at(j - 1);
- EffectsList::setParameter(newparam, QString(xName).replace("%i", QString::number(j)), QString::number(p.x()));
- EffectsList::setParameter(newparam, QString(yName).replace("%i", QString::number(j)), QString::number(p.y()));
- }
} else if (type == "wipe") {
Wipeval *wp = (Wipeval*)m_valueItems.value(paramName);
wipeInfo info;
connect(keyframe_list, SIGNAL(cellChanged(int, int)), this, SLOT(slotGenerateParams(int, int)));
m_position = new PositionEdit(i18n("Position"), 0, 0, 1, tc, widgetTable);
- ((QGridLayout*)widgetTable->layout())->addWidget(m_position, 2, 0, 1, -1);
+ ((QGridLayout*)widgetTable->layout())->addWidget(m_position, 3, 0, 1, -1);
m_showButtons = new QButtonGroup(this);
m_slidersLayout = new QGridLayout(param_sliders);
if (e.attribute("intimeline") == "1")
radio->setChecked(true);
- // make the radiobutton stay at the top
QVBoxLayout *radioLayout = new QVBoxLayout(this);
radioLayout->addWidget(radio, 0, Qt::AlignTop);
m_slidersLayout->addLayout(radioLayout, columnId, 1);
/** @brief Makes the first parameter visible in timeline if no parameter is selected. */
void checkVisibleParam();
+protected:
+ /** @brief Gets the position of a keyframe from the table.
+ * @param row Row of the keyframe in the table */
+ int getPos(int row);
+
+protected slots:
+ void slotAdjustKeyframeInfo(bool seek = true);
+
private:
QList <QDomElement> m_params;
int m_min;
PositionEdit *m_position;
void generateAllParams();
- /** @brief Gets the position of a keyframe from the table.
- * @param row Row of the keyframe in the table */
- int getPos(int row);
/** @brief Converts a frame value to timecode considering the frames vs. HH:MM:SS:FF setting.
* @return timecode */
QString getPosString(int pos);
void slotDeleteKeyframe();
void slotAddKeyframe();
void slotGenerateParams(int row, int column);
- void slotAdjustKeyframeInfo(bool seek = true);
void slotAdjustKeyframePos(int value);
void slotAdjustKeyframeValue(int value);
/** @brief Turns the seek to keyframe position setting on/off.
OnMonitorCornersItem::cornersActions OnMonitorCornersItem::getMode(QPointF pos, int *corner)
{
*corner = -1;
+ if (polygon().count() != 4)
+ return NoAction;
QPainterPath mouseArea;
pos = mapFromScene(pos);
if (KdenliveSettings::onmonitoreffects_cornersshowlines())
QGraphicsPolygonItem::paint(painter, option, widget);
+ if (polygon().count() != 4)
+ return;
+
double baseSize = 1 / painter->matrix().m11();
painter->setRenderHint(QPainter::Antialiasing);
painter->setBrush(QBrush(Qt::yellow));
<property name="margin">
<number>0</number>
</property>
- <item row="0" column="0" colspan="5">
+ <item row="1" column="0" colspan="5">
<widget class="QTableWidget" name="keyframe_list">
<property name="alternatingRowColors">
<bool>true</bool>
</attribute>
</widget>
</item>
- <item row="1" column="0">
+ <item row="2" column="0">
<widget class="QToolButton" name="button_add">
<property name="text">
<string>A</string>
</property>
</widget>
</item>
- <item row="1" column="1">
+ <item row="2" column="1">
<widget class="QToolButton" name="button_delete">
<property name="text">
<string>D</string>
</property>
</widget>
</item>
- <item row="1" column="2">
+ <item row="2" column="2">
<widget class="QToolButton" name="buttonResetKeyframe">
<property name="toolTip">
<string>Reset the parameters to their default values</string>
</property>
</widget>
</item>
- <item row="1" column="3">
+ <item row="2" column="3">
<widget class="QToolButton" name="buttonSeek">
<property name="toolTip">
<string>Seek to active keyframe</string>