1 /***************************************************************************
2 * Copyright (C) 2011 by Till Theato (root@ttill.de) *
3 * This file is part of Kdenlive (www.kdenlive.org). *
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. *
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. *
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 ***************************************************************************/
19 #include "simpletimelinewidget.h"
20 #include "kdenlivesettings.h"
22 #include <QStylePainter>
23 #include <QMouseEvent>
25 #include <KGlobalSettings>
26 #include <KColorScheme>
29 SimpleTimelineWidget::SimpleTimelineWidget(QWidget* parent) :
33 m_currentKeyframe(-1),
34 m_currentKeyframeOriginal(-1),
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);
50 void SimpleTimelineWidget::setKeyframes(QList <int> keyframes)
52 m_keyframes = keyframes;
54 m_currentKeyframe = m_currentKeyframeOriginal = -1;
55 emit atKeyframe(m_keyframes.contains(m_position));
59 void SimpleTimelineWidget::slotSetPosition(int pos)
61 if (pos != m_position) {
63 emit atKeyframe(m_keyframes.contains(m_position));
68 void SimpleTimelineWidget::slotAddKeyframe(int pos, int select)
73 m_keyframes.append(pos);
76 m_currentKeyframe = m_currentKeyframeOriginal = pos;
79 emit keyframeAdded(pos);
80 if (pos == m_position)
81 emit atKeyframe(true);
84 void SimpleTimelineWidget::slotAddRemove()
86 if (m_keyframes.contains(m_position))
87 slotRemoveKeyframe(m_position);
89 slotAddKeyframe(m_position);
92 void SimpleTimelineWidget::slotRemoveKeyframe(int pos)
94 m_keyframes.removeAll(pos);
95 if (m_currentKeyframe == pos)
96 m_currentKeyframe = m_currentKeyframeOriginal = -1;
98 emit keyframeRemoved(pos);
99 if (pos == m_position)
100 emit atKeyframe(false);
103 void SimpleTimelineWidget::setDuration(int dur)
108 void SimpleTimelineWidget::slotGoToNext()
110 if (m_position == m_duration)
113 foreach (const int &keyframe, m_keyframes) {
114 if (keyframe > m_position) {
115 slotSetPosition(keyframe);
116 emit positionChanged(keyframe);
117 emit atKeyframe(true);
122 // no keyframe after current position
123 slotSetPosition(m_duration);
124 emit positionChanged(m_duration);
125 emit atKeyframe(false);
128 void SimpleTimelineWidget::slotGoToPrev()
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);
142 // no keyframe before current position
144 emit positionChanged(0);
145 emit atKeyframe(false);
148 void SimpleTimelineWidget::mousePressEvent(QMouseEvent* event)
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;
163 // no keyframe next to mouse
164 m_currentKeyframe = m_currentKeyframeOriginal = -1;
166 emit positionChanged(pos);
167 emit atKeyframe(m_keyframes.contains(pos));
171 void SimpleTimelineWidget::mouseMoveEvent(QMouseEvent* event)
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))
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));
188 emit positionChanged(pos);
189 emit atKeyframe(m_keyframes.contains(pos));
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);
205 if (m_hoverKeyframe != -1) {
206 m_hoverKeyframe = -1;
207 setCursor(Qt::ArrowCursor);
213 void SimpleTimelineWidget::mouseReleaseEvent(QMouseEvent* event)
217 if (m_currentKeyframe >= 0) {
219 emit keyframeMoved(m_currentKeyframeOriginal, m_currentKeyframe);
223 void SimpleTimelineWidget::mouseDoubleClickEvent(QMouseEvent* event)
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);
240 m_keyframes.append(pos);
242 emit keyframeAdded(pos);
243 if (pos == m_position)
244 emit atKeyframe(true);
246 QWidget::mouseDoubleClickEvent(event);
250 void SimpleTimelineWidget::wheelEvent(QWheelEvent* event)
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);
257 m_position = qBound(0, m_position + change, m_duration);
258 emit positionChanged(m_position);
260 emit atKeyframe(m_keyframes.contains(m_position));
264 void SimpleTimelineWidget::paintEvent(QPaintEvent* event)
268 QStylePainter p(this);
269 m_scale = width() / (double)(m_duration);
270 p.translate(0, m_lineHeight);
272 p.setPen(m_colKeyframe);
273 p.setBrush(m_colKeyframeBg);
278 QPolygonF keyframe = QPolygonF() << QPointF(0, -10) << QPointF(-4, -6) << QPointF(0, -2) << QPointF(4, -6);
280 foreach (const int &pos, m_keyframes) {
282 tmp.translate(pos * m_scale, 0);
283 if (pos == m_currentKeyframe || pos == m_hoverKeyframe)
284 p.setBrush(m_colSelected);
286 p.drawConvexPolygon(tmp);
287 p.drawLine(QLineF(0, -1, 0, 5).translated(pos * m_scale, 0));
289 if (pos == m_currentKeyframe || pos == m_hoverKeyframe)
290 p.setBrush(m_colKeyframeBg);
293 p.setPen(palette().dark().color());
298 p.drawLine(0, 0, width(), 0);
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);
309 #include "simpletimelinewidget.moc"