]> git.sesse.net Git - kdenlive/blob - src/simplekeyframes/simpletimelinewidget.cpp
9838005acbcf12954bd956f6554373f17980f513
[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
21 #include <QPainter>
22 #include <QMouseEvent>
23
24
25 SimpleTimelineWidget::SimpleTimelineWidget(QWidget* parent) :
26         QWidget(parent),
27         m_min(0),
28         m_max(1),
29         m_position(0),
30         m_currentKeyframe(-1),
31         m_currentKeyframeOriginal(-1),
32         m_lineHeight(10),
33         m_scale(1)
34 {
35     setMouseTracking(true);
36     setMinimumSize(QSize(150, 20));
37     setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum));
38 }
39
40 void SimpleTimelineWidget::setKeyframes(QList <int> keyframes)
41 {
42     m_keyframes = keyframes;
43     qSort(m_keyframes);
44     m_currentKeyframe = m_currentKeyframeOriginal = -1;
45     update();
46 }
47
48 void SimpleTimelineWidget::slotSetPosition(int pos)
49 {
50     m_position = pos;
51     update();
52 }
53
54 void SimpleTimelineWidget::slotAddKeyframe(int pos, int select)
55 {
56     if (pos < 0)
57         pos = m_position;
58
59     m_keyframes.append(pos);
60     qSort(m_keyframes);
61     if (select)
62         m_currentKeyframe = m_currentKeyframeOriginal = pos;
63     update();
64
65     emit keyframeAdded(pos);
66 }
67
68 void SimpleTimelineWidget::slotAddRemove()
69 {
70     if (m_keyframes.contains(m_position))
71         slotRemoveKeyframe(m_position);
72     else
73         slotAddKeyframe(m_position);
74 }
75
76 void SimpleTimelineWidget::slotRemoveKeyframe(int pos)
77 {
78     m_keyframes.removeAll(pos);
79     if (m_currentKeyframe == pos)
80         m_currentKeyframe = m_currentKeyframeOriginal = -1;
81     update();
82     emit keyframeRemoved(pos);
83 }
84
85 void SimpleTimelineWidget::setRange(int min, int max)
86 {
87     m_min = min;
88     m_max = max;
89 }
90
91 void SimpleTimelineWidget::slotGoToNext()
92 {
93     foreach (const int &keyframe, m_keyframes) {
94         if (keyframe > m_position) {
95             slotSetPosition(keyframe);
96             emit positionChanged(keyframe);
97             return;
98         }
99     }
100
101     // no keyframe after current position
102     slotSetPosition(m_max);
103     emit positionChanged(m_max);
104 }
105
106 void SimpleTimelineWidget::slotGoToPrev()
107 {
108     for (int i = m_keyframes.count() - 1; i >= 0; --i) {
109         if (m_keyframes.at(i) < m_position) {
110             slotSetPosition(m_keyframes.at(i));
111             emit positionChanged(m_keyframes.at(i));
112             return;
113         }
114     }
115
116     // no keyframe before current position
117     slotSetPosition(m_min);
118     emit positionChanged(m_min);
119 }
120
121 void SimpleTimelineWidget::mousePressEvent(QMouseEvent* event)
122 {
123     if (qAbs(event->y() - m_lineHeight) < m_lineHeight / 5. && event->button() == Qt::LeftButton)  {
124         int pos = (event->x() - 5) / m_scale;
125         foreach(const int &keyframe, m_keyframes) {
126             if (qAbs(keyframe - pos) < 5) {
127                 m_currentKeyframeOriginal = keyframe;
128                 m_currentKeyframe = pos;
129                 update();
130                 return;
131             }
132         }
133     }
134
135     // no keyframe next to mouse
136     m_currentKeyframe = m_currentKeyframeOriginal = -1;
137     m_position = (event->x() - 5) / m_scale;
138     emit positionChanged(m_position);
139     update();
140 }
141
142 void SimpleTimelineWidget::mouseMoveEvent(QMouseEvent* event)
143 {
144     if (event->buttons() & Qt::LeftButton) {
145         int pos = qBound(m_min, (int)((event->x() - 5) / m_scale), m_max);
146         if (m_currentKeyframe >= 0) {
147             m_currentKeyframe = pos;
148             emit keyframeMoving(m_currentKeyframeOriginal, m_currentKeyframe);
149         } else {
150             m_position = pos;
151             emit positionChanged(pos);
152         }
153         update();
154         return;
155     }
156
157     // cursor
158 }
159
160 void SimpleTimelineWidget::mouseReleaseEvent(QMouseEvent* event)
161 {
162     if (m_currentKeyframe > 0) {
163         emit keyframeMoved(m_currentKeyframeOriginal, m_currentKeyframe);
164     }
165 }
166
167 void SimpleTimelineWidget::wheelEvent(QWheelEvent* event)
168 {
169     int change = event->delta() < 0 ? -1 : 1;
170     if (m_currentKeyframe > 0) {
171         m_currentKeyframe = qBound(m_min, m_currentKeyframe + change, m_max);
172         emit keyframeMoved(m_currentKeyframeOriginal, m_currentKeyframe);
173     } else {
174         m_position = qBound(m_min, m_position + change, m_max);
175         emit positionChanged(m_position);
176     }
177     update();
178 }
179
180 void SimpleTimelineWidget::paintEvent(QPaintEvent* event)
181 {
182     QPainter p(this);
183     int min = 5;
184     int max = width() - 6;
185     m_scale = (max - min) / (double)(m_max - m_min);
186     p.translate(min, m_lineHeight);
187
188     p.setPen(QPen(palette().foreground().color(), 1, Qt::SolidLine));
189
190     /*
191      * Time-"line"
192      */
193     p.drawLine(0, 0, max, 0);
194
195     /*
196      * current position
197      */
198     p.fillRect(QRectF(-1, -10, 3, 20).translated(m_position * m_scale, 0), QBrush(palette().foreground().color(), Qt::SolidPattern));
199
200     /*
201      * keyframes
202      */
203     p.setPen(QPen(palette().highlight().color(), 1, Qt::SolidLine));
204     p.setBrush(Qt::NoBrush);
205     QPolygonF keyframe = QPolygonF() << QPointF(0, -4) << QPointF(-4, 0) << QPointF(0, 4) << QPointF(4, 0);
206     QPolygonF tmp;
207     foreach (const int &pos, m_keyframes) {
208         tmp = keyframe;
209         tmp.translate(pos * m_scale, 0);
210         if (pos == m_currentKeyframe)
211             p.setBrush(QBrush(palette().highlight().color(), Qt::SolidPattern));
212
213         p.drawConvexPolygon(tmp);
214
215         if (pos == m_currentKeyframe)
216             p.setBrush(Qt::NoBrush);
217     }
218 }
219
220 #include "simpletimelinewidget.moc"