]> git.sesse.net Git - kdenlive/blob - src/simplekeyframes/simpletimelinewidget.cpp
Integrate with the required MLT hooks for getting Movit to work.
[kdenlive] / src / simplekeyframes / simpletimelinewidget.cpp
1 /***************************************************************************
2  *   Copyright (C) 2011 by Till Theato (root@ttill.de)                     *
3  *   This file is part of Kdenlive (www.kdenlive.org).                     *
4  *                                                                         *
5  *   Kdenlive is free software: you can redistribute it and/or modify      *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation, either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   Kdenlive is distributed in the hope that it will be useful,           *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with Kdenlive.  If not, see <http://www.gnu.org/licenses/>.     *
17  ***************************************************************************/
18
19 #include "simpletimelinewidget.h"
20 #include "kdenlivesettings.h"
21
22 #include <QStylePainter>
23 #include <QMouseEvent>
24
25 #include <KGlobalSettings>
26 #include <KColorScheme>
27
28
29 SimpleTimelineWidget::SimpleTimelineWidget(QWidget* parent) :
30         QWidget(parent),
31         m_duration(1),
32         m_position(0),
33         m_currentKeyframe(-1),
34         m_currentKeyframeOriginal(-1),
35         m_hoverKeyframe(-1),
36         m_lineHeight(10),
37         m_scale(1)
38 {
39     setMouseTracking(true);
40     setMinimumSize(QSize(150, 20));
41     setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum));
42     setFont(KGlobalSettings::toolBarFont());
43     QPalette p = palette();
44     KColorScheme scheme(p.currentColorGroup(), KColorScheme::Window, KSharedConfig::openConfig(KdenliveSettings::colortheme()));
45     m_colSelected = scheme.decoration(KColorScheme::HoverColor).color();
46     m_colKeyframe = scheme.foreground(KColorScheme::LinkText).color();
47     m_colKeyframeBg = scheme.shade(KColorScheme::MidShade);
48 }
49
50 void SimpleTimelineWidget::setKeyframes(const QList<int> &keyframes)
51 {
52     m_keyframes = keyframes;
53     qSort(m_keyframes);
54     m_currentKeyframe = m_currentKeyframeOriginal = -1;
55     emit atKeyframe(m_keyframes.contains(m_position));
56     update();
57 }
58
59 void SimpleTimelineWidget::slotSetPosition(int pos)
60 {
61     if (pos != m_position) {
62         m_position = pos;
63         emit atKeyframe(m_keyframes.contains(m_position));
64         update();
65     }
66 }
67
68 void SimpleTimelineWidget::slotAddKeyframe(int pos, int select)
69 {
70     if (pos < 0)
71         pos = m_position;
72
73     m_keyframes.append(pos);
74     qSort(m_keyframes);
75     if (select)
76         m_currentKeyframe = m_currentKeyframeOriginal = pos;
77     update();
78
79     emit keyframeAdded(pos);
80     if (pos == m_position)
81         emit atKeyframe(true);
82 }
83
84 void SimpleTimelineWidget::slotAddRemove()
85 {
86     if (m_keyframes.contains(m_position))
87         slotRemoveKeyframe(m_position);
88     else
89         slotAddKeyframe(m_position);
90 }
91
92 void SimpleTimelineWidget::slotRemoveKeyframe(int pos)
93 {
94     m_keyframes.removeAll(pos);
95     if (m_currentKeyframe == pos)
96         m_currentKeyframe = m_currentKeyframeOriginal = -1;
97     update();
98     emit keyframeRemoved(pos);
99     if (pos == m_position)
100         emit atKeyframe(false);
101 }
102
103 void SimpleTimelineWidget::setDuration(int dur)
104 {
105     m_duration = dur;
106 }
107
108 void SimpleTimelineWidget::slotGoToNext()
109 {
110     if (m_position == m_duration)
111         return;
112
113     foreach (const int &keyframe, m_keyframes) {
114         if (keyframe > m_position) {
115             slotSetPosition(keyframe);
116             emit positionChanged(keyframe);
117             emit atKeyframe(true);
118             return;
119         }
120     }
121
122     // no keyframe after current position
123     slotSetPosition(m_duration);
124     emit positionChanged(m_duration);
125     emit atKeyframe(false);
126 }
127
128 void SimpleTimelineWidget::slotGoToPrev()
129 {
130     if (m_position == 0)
131         return;
132
133     for (int i = m_keyframes.count() - 1; i >= 0; --i) {
134         if (m_keyframes.at(i) < m_position) {
135             slotSetPosition(m_keyframes.at(i));
136             emit positionChanged(m_keyframes.at(i));
137             emit atKeyframe(true);
138             return;
139         }
140     }
141
142     // no keyframe before current position
143     slotSetPosition(0);
144     emit positionChanged(0);
145     emit atKeyframe(false);
146 }
147
148 void SimpleTimelineWidget::mousePressEvent(QMouseEvent* event)
149 {
150     int pos = event->x() / m_scale;
151     if (event->y() < m_lineHeight && event->button() == Qt::LeftButton)  {
152         foreach(const int &keyframe, m_keyframes) {
153             if (qAbs(keyframe - pos) < 5) {
154                 m_currentKeyframeOriginal = keyframe;
155                 m_keyframes[m_keyframes.indexOf(keyframe)] = pos;
156                 m_currentKeyframe = pos;
157                 update();
158                 return;
159             }
160         }
161     }
162
163     // no keyframe next to mouse
164     m_currentKeyframe = m_currentKeyframeOriginal = -1;
165     m_position = pos;
166     emit positionChanged(pos);
167     emit atKeyframe(m_keyframes.contains(pos));
168     update();
169 }
170
171 void SimpleTimelineWidget::mouseMoveEvent(QMouseEvent* event)
172 {
173     int pos = qBound(0, (int)(event->x() / m_scale), m_duration);
174     if (event->buttons() & Qt::LeftButton) {
175         if (m_currentKeyframe >= 0) {
176             if (!m_keyframes.contains(pos)) {
177                 // snap to position cursor
178                 if (KdenliveSettings::snaptopoints() && qAbs(pos - m_position) < 5 && !m_keyframes.contains(m_position))
179                     pos = m_position;
180                 // should we maybe sort here?
181                 m_keyframes[m_keyframes.indexOf(m_currentKeyframe)] = pos;
182                 m_currentKeyframe = pos;
183                 emit keyframeMoving(m_currentKeyframeOriginal, m_currentKeyframe);
184                 emit atKeyframe(m_keyframes.contains(m_position));
185             }
186         } else {
187             m_position = pos;
188             emit positionChanged(pos);
189             emit atKeyframe(m_keyframes.contains(pos));
190         }
191         update();
192         return;
193     } else {
194         if (event->y() < m_lineHeight) {
195             foreach(const int &keyframe, m_keyframes) {
196                 if (qAbs(keyframe - pos) < 5) {
197                     m_hoverKeyframe = keyframe;
198                     setCursor(Qt::PointingHandCursor);
199                     update();
200                     return;
201                 }
202             }
203         }
204
205         if (m_hoverKeyframe != -1) {
206             m_hoverKeyframe = -1;
207             setCursor(Qt::ArrowCursor);
208             update();
209         }
210     }
211 }
212
213 void SimpleTimelineWidget::mouseReleaseEvent(QMouseEvent* event)
214 {
215     Q_UNUSED(event)
216
217     if (m_currentKeyframe >= 0) {
218         qSort(m_keyframes);
219         emit keyframeMoved(m_currentKeyframeOriginal, m_currentKeyframe);
220     }
221 }
222
223 void SimpleTimelineWidget::mouseDoubleClickEvent(QMouseEvent* event)
224 {
225     if (event->button() == Qt::LeftButton && event->y() < m_lineHeight) {
226         int pos = qBound(0, (int)(event->x() / m_scale), m_duration);
227         foreach(const int &keyframe, m_keyframes) {
228             if (qAbs(keyframe - pos) < 5) {
229                 m_keyframes.removeAll(keyframe);
230                 if (keyframe == m_currentKeyframe)
231                     m_currentKeyframe = m_currentKeyframeOriginal = -1;
232                 emit keyframeRemoved(keyframe);
233                 if (keyframe == m_position)
234                     emit atKeyframe(false);
235                 return;
236             }
237         }
238
239         // add new keyframe
240         m_keyframes.append(pos);
241         qSort(m_keyframes);
242         emit keyframeAdded(pos);
243         if (pos == m_position)
244             emit atKeyframe(true);
245     } else {
246         QWidget::mouseDoubleClickEvent(event);
247     }
248 }
249
250 void SimpleTimelineWidget::wheelEvent(QWheelEvent* event)
251 {
252     int change = event->delta() < 0 ? -1 : 1;
253     /*if (m_currentKeyframe > 0) {
254         m_currentKeyframe = qBound(0, m_currentKeyframe + change, m_duration);
255         emit keyframeMoved(m_currentKeyframeOriginal, m_currentKeyframe);
256     } else { */
257         m_position = qBound(0, m_position + change, m_duration);
258         emit positionChanged(m_position);
259 //     }
260     emit atKeyframe(m_keyframes.contains(m_position));
261     update();
262 }
263
264 void SimpleTimelineWidget::paintEvent(QPaintEvent* event)
265 {
266     Q_UNUSED(event)
267
268     QStylePainter p(this);
269     m_scale = width() / (double)(m_duration);
270     p.translate(0, m_lineHeight);
271
272     p.setPen(m_colKeyframe);
273     p.setBrush(m_colKeyframeBg);
274
275     /*
276      * keyframes
277      */
278     QPolygonF keyframe = QPolygonF() << QPointF(0, -10) << QPointF(-4, -6) << QPointF(0, -2) << QPointF(4, -6);
279     QPolygonF tmp;
280     foreach (const int &pos, m_keyframes) {
281         tmp = keyframe;
282         tmp.translate(pos * m_scale, 0);
283         if (pos == m_currentKeyframe || pos == m_hoverKeyframe)
284             p.setBrush(m_colSelected);
285
286         p.drawConvexPolygon(tmp);
287         p.drawLine(QLineF(0, -1, 0, 5).translated(pos * m_scale, 0));
288
289         if (pos == m_currentKeyframe || pos == m_hoverKeyframe)
290             p.setBrush(m_colKeyframeBg);
291     }
292
293     p.setPen(palette().dark().color());
294
295     /*
296      * Time-"line"
297      */
298     p.drawLine(0, 0, width(), 0);
299
300     /*
301      * current position
302      */
303     QPolygonF position = QPolygonF() << QPointF(0, 1) << QPointF(5, 6) << QPointF(-5, 6);
304     position.translate(m_position * m_scale, 0);
305     p.setBrush(palette().dark().color());
306     p.drawConvexPolygon(position);
307 }
308
309 #include "simpletimelinewidget.moc"