]> git.sesse.net Git - kdenlive/blob - src/simplekeyframes/simpletimelinewidget.cpp
rotoscoping: make keyframe timeline look the same as the one used for geometries...
[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_lineHeight(10),
36         m_scale(1)
37 {
38     setMouseTracking(true);
39     setMinimumSize(QSize(150, 20));
40     setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum));
41     setFont(KGlobalSettings::toolBarFont());
42     QPalette p = palette();
43     KColorScheme scheme(p.currentColorGroup(), KColorScheme::Window, KSharedConfig::openConfig(KdenliveSettings::colortheme()));
44     m_colSelected = scheme.decoration(KColorScheme::HoverColor).color();
45     m_colKeyframe = scheme.foreground(KColorScheme::LinkText).color();
46     m_colKeyframeBg = scheme.shade(KColorScheme::MidShade);
47 }
48
49 void SimpleTimelineWidget::setKeyframes(QList <int> keyframes)
50 {
51     m_keyframes = keyframes;
52     qSort(m_keyframes);
53     m_currentKeyframe = m_currentKeyframeOriginal = -1;
54     update();
55 }
56
57 void SimpleTimelineWidget::slotSetPosition(int pos)
58 {
59     m_position = pos;
60     update();
61 }
62
63 void SimpleTimelineWidget::slotAddKeyframe(int pos, int select)
64 {
65     if (pos < 0)
66         pos = m_position;
67
68     m_keyframes.append(pos);
69     qSort(m_keyframes);
70     if (select)
71         m_currentKeyframe = m_currentKeyframeOriginal = pos;
72     update();
73
74     emit keyframeAdded(pos);
75 }
76
77 void SimpleTimelineWidget::slotAddRemove()
78 {
79     if (m_keyframes.contains(m_position))
80         slotRemoveKeyframe(m_position);
81     else
82         slotAddKeyframe(m_position);
83 }
84
85 void SimpleTimelineWidget::slotRemoveKeyframe(int pos)
86 {
87     m_keyframes.removeAll(pos);
88     if (m_currentKeyframe == pos)
89         m_currentKeyframe = m_currentKeyframeOriginal = -1;
90     update();
91     emit keyframeRemoved(pos);
92 }
93
94 void SimpleTimelineWidget::setDuration(int dur)
95 {
96     m_duration = dur;
97 }
98
99 void SimpleTimelineWidget::slotGoToNext()
100 {
101     foreach (const int &keyframe, m_keyframes) {
102         if (keyframe > m_position) {
103             slotSetPosition(keyframe);
104             emit positionChanged(keyframe);
105             return;
106         }
107     }
108
109     // no keyframe after current position
110     slotSetPosition(m_duration);
111     emit positionChanged(m_duration);
112 }
113
114 void SimpleTimelineWidget::slotGoToPrev()
115 {
116     for (int i = m_keyframes.count() - 1; i >= 0; --i) {
117         if (m_keyframes.at(i) < m_position) {
118             slotSetPosition(m_keyframes.at(i));
119             emit positionChanged(m_keyframes.at(i));
120             return;
121         }
122     }
123
124     // no keyframe before current position
125     slotSetPosition(0);
126     emit positionChanged(0);
127 }
128
129 void SimpleTimelineWidget::mousePressEvent(QMouseEvent* event)
130 {
131     int pos = event->x() / m_scale;
132     if (event->y() < m_lineHeight && event->button() == Qt::LeftButton)  {
133         foreach(const int &keyframe, m_keyframes) {
134             if (qAbs(keyframe - pos) < 5) {
135                 m_currentKeyframeOriginal = keyframe;
136                 m_currentKeyframe = pos;
137                 update();
138                 return;
139             }
140         }
141     }
142
143     // no keyframe next to mouse
144     m_currentKeyframe = m_currentKeyframeOriginal = -1;
145     m_position = pos;
146     emit positionChanged(pos);
147     update();
148 }
149
150 void SimpleTimelineWidget::mouseMoveEvent(QMouseEvent* event)
151 {
152     if (event->buttons() & Qt::LeftButton) {
153         int pos = qBound(0, (int)(event->x() / m_scale), m_duration);
154         if (m_currentKeyframe >= 0) {
155             m_currentKeyframe = pos;
156             emit keyframeMoving(m_currentKeyframeOriginal, m_currentKeyframe);
157         } else {
158             m_position = pos;
159             emit positionChanged(pos);
160         }
161         update();
162         return;
163     }
164
165     // cursor
166 }
167
168 void SimpleTimelineWidget::mouseReleaseEvent(QMouseEvent* event)
169 {
170     Q_UNUSED(event)
171
172     if (m_currentKeyframe > 0) {
173         emit keyframeMoved(m_currentKeyframeOriginal, m_currentKeyframe);
174     }
175 }
176
177 void SimpleTimelineWidget::wheelEvent(QWheelEvent* event)
178 {
179     int change = event->delta() < 0 ? -1 : 1;
180     if (m_currentKeyframe > 0) {
181         m_currentKeyframe = qBound(0, m_currentKeyframe + change, m_duration);
182         emit keyframeMoved(m_currentKeyframeOriginal, m_currentKeyframe);
183     } else {
184         m_position = qBound(0, m_position + change, m_duration);
185         emit positionChanged(m_position);
186     }
187     update();
188 }
189
190 void SimpleTimelineWidget::paintEvent(QPaintEvent* event)
191 {
192     Q_UNUSED(event)
193
194     QStylePainter p(this);
195     m_scale = width() / (double)(m_duration);
196     p.translate(0, m_lineHeight);
197
198     p.setPen(m_colKeyframe);
199     p.setBrush(m_colKeyframeBg);
200
201     /*
202      * keyframes
203      */
204     QPolygonF keyframe = QPolygonF() << QPointF(0, -10) << QPointF(-4, -6) << QPointF(0, -2) << QPointF(4, -6);
205     QPolygonF tmp;
206     foreach (const int &pos, m_keyframes) {
207         tmp = keyframe;
208         tmp.translate(pos * m_scale, 0);
209         if (pos == m_currentKeyframe)
210             p.setBrush(m_colSelected);
211
212         p.drawConvexPolygon(tmp);
213         p.drawLine(QLineF(0, -1, 0, 5).translated(pos * m_scale, 0));
214
215         if (pos == m_currentKeyframe)
216             p.setBrush(m_colKeyframeBg);
217     }
218
219
220     p.setPen(palette().dark().color());
221
222     /*
223      * Time-"line"
224      */
225     p.drawLine(0, 0, width(), 0);
226
227     /*
228      * current position
229      */
230     QPolygonF position = QPolygonF() << QPointF(0, 1) << QPointF(5, 6) << QPointF(-5, 6);
231     position.translate(m_position * m_scale, 0);
232     p.setBrush(palette().dark().color());
233     p.drawConvexPolygon(position);
234 }
235
236 #include "simpletimelinewidget.moc"