]> git.sesse.net Git - kdenlive/blob - src/cornerswidget.cpp
Fix pedantic, fix forward declaration/include
[kdenlive] / src / cornerswidget.cpp
1 /***************************************************************************
2  *   Copyright (C) 2010 by Till Theato (root@ttill.de)                     *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
18  ***************************************************************************/
19
20 #include "cornerswidget.h"
21 #include "monitor.h"
22 #include "monitorscene.h"
23 #include "monitoreditwidget.h"
24 #include "onmonitoritems/onmonitorcornersitem.h"
25 #include "renderer.h"
26 #include "kdenlivesettings.h"
27
28 #include <QGraphicsView>
29 #include <QGridLayout>
30 #include <QToolButton>
31
32 #include <KIcon>
33
34 inline int lerp( const int a, const int b, double t )
35 {
36     return a + (b - a) * t;
37 }
38
39 CornersWidget::CornersWidget(Monitor *monitor, const QDomElement& e, int minFrame, int maxFrame, const Timecode &tc, int activeKeyframe, QWidget* parent) :
40         KeyframeEdit(e, minFrame, maxFrame, tc, activeKeyframe, parent),
41         m_monitor(monitor),
42         m_showScene(true),
43         m_pos(0)
44 {
45     MonitorEditWidget *edit = monitor->getEffectEdit();
46     m_scene = edit->getScene();
47     m_scene->cleanup();
48
49     m_item = new OnMonitorCornersItem();
50     m_scene->addItem(m_item);
51
52     // TODO: Better Icons
53     edit->removeCustomControls();
54     edit->addCustomButton(KIcon("transform-move"), i18n("Show additional controls"), this, SLOT(slotShowControls(bool)),
55                           true, KdenliveSettings::onmonitoreffects_cornersshowcontrols());
56     edit->addCustomButton(KIcon("insert-horizontal-rule"), i18n("Show/Hide the lines connecting the corners"), this, SLOT(slotShowLines(bool)),
57                           true, KdenliveSettings::onmonitoreffects_cornersshowlines());
58
59     connect(m_item, SIGNAL(changed()), this, SLOT(slotUpdateProperties()));
60     connect(m_scene, SIGNAL(addKeyframe()), this, SLOT(slotInsertKeyframe()));
61
62     connect(keyframe_list, SIGNAL(cellChanged(int,int)), this, SLOT(slotUpdateItem()));
63     m_scene->centerView();
64 }
65
66 CornersWidget::~CornersWidget()
67 {
68     m_scene->removeItem(m_item);
69     delete m_item;
70     if (m_monitor) {
71         MonitorEditWidget *edit = m_monitor->getEffectEdit();
72         edit->removeCustomControls();
73     }
74 }
75
76 void CornersWidget::addParameter(QDomElement e, int activeKeyframe)
77 {
78     KeyframeEdit::addParameter(e, activeKeyframe);
79
80     if (!m_item->polygon().count())
81         slotUpdateItem();
82 }
83
84 void CornersWidget::slotUpdateItem()
85 {
86     if (keyframe_list->columnCount() < 8)
87         return;
88
89     QTableWidgetItem *keyframe, *keyframeOld;
90     keyframe = keyframeOld = keyframe_list->item(0, 0);
91     for (int row = 0; row < keyframe_list->rowCount(); ++row) {
92         keyframeOld = keyframe;
93         keyframe = keyframe_list->item(row, 0);
94         if (getPos(row) >= m_pos)
95             break;
96     }
97
98     QList<QPointF> points, pointsPrev, pointsNext;
99     pointsPrev = getPoints(keyframeOld);
100     pointsNext = getPoints(keyframe);
101     if (pointsPrev.count() != 4 || pointsNext.count() != 4)
102         return;
103
104     qreal position = (m_pos - getPos(keyframeOld->row())) / (qreal)( getPos(keyframe->row()) - getPos(keyframeOld->row()) + 1 );
105
106     if (keyframeOld  == keyframe) {
107         points = pointsNext;
108     } else {
109         for (int i = 0; i < 4; ++i)
110             points.append(QLineF(pointsPrev.at(i), pointsNext.at(i)).pointAt(position));
111     }
112
113     m_scene->blockSignals(true);
114     m_item->setPolygon(QPolygonF() << points.at(0) << points.at(1) << points.at(2) << points.at(3));
115     m_scene->blockSignals(false);
116
117     bool enable = getPos(keyframe->row()) == m_pos || keyframe_list->rowCount() == 1;
118     m_item->setEnabled(enable);
119     m_scene->setEnabled(enable);
120 }
121
122 void CornersWidget::slotUpdateProperties()
123 {
124     if (keyframe_list->columnCount() < 8)
125         return;
126
127     QPolygonF pol = m_item->polygon();
128
129     QTableWidgetItem *item = keyframe_list->currentItem();
130     double val;
131     for (int col = 0; col < 8; col++) {
132         if (col % 2 == 0)
133             val = pol.at(col / 2).x() / (double)m_monitor->render->frameRenderWidth();
134         else
135             val = pol.at(col / 2).y() / (double)m_monitor->render->renderHeight();
136         val *= 2000;
137         val += 2000;
138         QTableWidgetItem *nitem = keyframe_list->item(item->row(), col);
139         if (nitem->text().toInt() != (int)val)
140             nitem->setText(QString::number((int)val));
141     }
142
143     slotAdjustKeyframeInfo(false);
144 }
145
146 QList<QPointF> CornersWidget::getPoints(QTableWidgetItem* keyframe)
147 {
148     QList<QPointF> points;
149
150     if (!keyframe)
151         return points;
152
153     double val;
154     for (int col = 0; col < 8; col++) {
155         if (!keyframe_list->item(keyframe->row(), col))
156             return QList<QPointF>();
157         val = (keyframe_list->item(keyframe->row(), col)->text().toInt() - 2000) / 2000.;
158         if (col % 2 == 0)
159             points << QPointF(val * m_monitor->render->frameRenderWidth(), 0);
160         else
161             points[col / 2].setY(val * m_monitor->render->renderHeight());
162     }
163     return points;
164 }
165
166
167 void CornersWidget::slotShowLines(bool show)
168 {
169     KdenliveSettings::setOnmonitoreffects_cornersshowlines(show);
170     m_item->update();
171 }
172
173 void CornersWidget::slotShowControls(bool show)
174 {
175     KdenliveSettings::setOnmonitoreffects_cornersshowcontrols(show);
176     m_item->update();
177 }
178
179 void CornersWidget::slotSyncPosition(int relTimelinePos)
180 {
181     if (keyframe_list->rowCount()) {
182         relTimelinePos = qBound(0, relTimelinePos, m_max);
183         if (relTimelinePos != m_pos - m_min) {
184             m_pos = relTimelinePos + m_min;
185             slotUpdateItem();
186         }
187     }
188 }
189
190 void CornersWidget::slotInsertKeyframe()
191 {
192     keyframe_list->blockSignals(true);
193
194     int row;
195     QTableWidgetItem *keyframe, *keyframeOld;
196     keyframe = keyframeOld = keyframe_list->item(0, 0);
197     for (row = 0; row < keyframe_list->rowCount(); ++row) {
198         keyframeOld = keyframe;
199         keyframe = keyframe_list->item(row, 0);
200         if (getPos(row) >= m_pos)
201             break;
202     }
203
204
205     int pos2;
206     if (row == keyframe_list->rowCount()) {
207         pos2 = m_max;
208     } else {
209         pos2 = getPos(row);
210         if (pos2 == m_pos)
211             return;
212     }
213
214     int pos1 = 0;
215     if (row > 0)
216         pos1 = getPos(row - 1);
217
218     int col = keyframe_list->currentColumn();
219     double pos = (m_pos - pos1) / (double)(pos2 - pos1 + 1);
220
221     keyframe_list->insertRow(row);
222     keyframe_list->setVerticalHeaderItem(row, new QTableWidgetItem(getPosString(m_pos)));
223
224     QPolygonF pol = m_item->polygon();
225     double val;
226     for (int i = 0; i < keyframe_list->columnCount(); ++i) {
227         if (i < 8) {
228             if (i % 2 == 0)
229                 val = pol.at(i / 2).x() / (double)m_monitor->render->frameRenderWidth();
230             else
231                 val = pol.at(i / 2).y() / (double)m_monitor->render->renderHeight();
232             val *= 2000;
233             val += 2000;
234             keyframe_list->setItem(row, i, new QTableWidgetItem(QString::number((int)val)));
235         } else {
236             keyframe_list->setItem(row, i, new QTableWidgetItem(QString::number(lerp(keyframe_list->item(keyframeOld->row(), i)->text().toInt(), keyframe_list->item(keyframe->row(), i)->text().toInt(), pos))));
237         }
238     }
239
240     keyframe_list->resizeRowsToContents();
241     slotAdjustKeyframeInfo();
242     keyframe_list->blockSignals(false);
243     generateAllParams();
244     button_delete->setEnabled(true);
245     keyframe_list->setCurrentCell(row, col);
246     keyframe_list->selectRow(row);
247 }
248
249
250 #include "cornerswidget.moc"