]> git.sesse.net Git - kdenlive/blob - src/timecodedisplay.cpp
Make it easier to edit timecode by selecting the digit after the cursor
[kdenlive] / src / timecodedisplay.cpp
1 /* This file is part of the KDE project
2    Copyright (c) 2010 Jean-Baptiste Mardelle <jb@kdenlive.org>
3
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public
6    License as published by the Free Software Foundation; either
7    version 2 of the License, or (at your option) any later version.
8
9    This library 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 GNU
12    Library General Public License for more details.
13
14    You should have received a copy of the GNU Library General Public License
15    along with this library; see the file COPYING.LIB.  If not, write to
16    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18 */
19
20 #include "timecodedisplay.h"
21 #include "kdenlivesettings.h"
22
23 #include <QLineEdit>
24 #include <QValidator>
25 #include <QMouseEvent>
26
27 #include <kglobal.h>
28 #include <klocale.h>
29 #include <kdebug.h>
30
31
32 TimecodeDisplay::TimecodeDisplay(Timecode t, QWidget *parent)
33         : QWidget(parent),
34         m_timecode(t),
35         m_minimum(0),
36         m_maximum(-1)
37 {
38     setupUi(this);
39     lineedit->setFont(KGlobalSettings::toolBarFont());
40     QFontMetrics fm = lineedit->fontMetrics();
41     lineedit->setMaximumWidth(fm.width("88:88:88:888"));
42     setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
43
44     setTimeCodeFormat(KdenliveSettings::frametimecode(), true);
45
46     connect(uparrow, SIGNAL(clicked()), this, SLOT(slotValueUp()));
47     connect(downarrow, SIGNAL(clicked()), this, SLOT(slotValueDown()));
48     connect(lineedit, SIGNAL(editingFinished()), this, SIGNAL(editingFinished()));
49     connect(lineedit, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(slotCursorPositionChanged(int, int)));
50 }
51
52 void TimecodeDisplay::slotValueUp()
53 {
54     int val = getValue();
55     val++;
56     setValue(val);
57     lineedit->clearFocus();
58     emit editingFinished();
59 }
60
61 void TimecodeDisplay::slotValueDown()
62 {
63     int val = getValue();
64     val--;
65     setValue(val);
66     lineedit->clearFocus();
67     emit editingFinished();
68 }
69
70 void TimecodeDisplay::setTimeCodeFormat(bool frametimecode, bool init)
71 {
72     if (!init && m_frametimecode == frametimecode) return;
73     int val = getValue();
74     m_frametimecode = frametimecode;
75     if (m_frametimecode) {
76         QIntValidator *valid = new QIntValidator(lineedit);
77         valid->setBottom(0);
78         lineedit->setValidator(valid);
79     } else {
80         lineedit->setValidator(m_timecode.validator());
81     }
82     setValue(val);
83 }
84
85 void TimecodeDisplay::slotUpdateTimeCodeFormat()
86 {
87     setTimeCodeFormat(KdenliveSettings::frametimecode());
88 }
89
90 void TimecodeDisplay::updateTimeCode(Timecode t)
91 {
92     m_timecode = t;
93     setTimeCodeFormat(KdenliveSettings::frametimecode());
94 }
95
96 void TimecodeDisplay::keyPressEvent(QKeyEvent *e)
97 {
98     if (e->key() == Qt::Key_Up)
99         slotValueUp();
100     else if (e->key() == Qt::Key_Down)
101         slotValueDown();
102     else
103         QWidget::keyPressEvent(e);
104 }
105
106 void TimecodeDisplay::wheelEvent(QWheelEvent *e)
107 {
108     if (e->delta() > 0)
109         slotValueUp();
110     else
111         slotValueDown();
112 }
113
114
115 int TimecodeDisplay::maximum() const
116 {
117     return m_maximum;
118 }
119
120 int TimecodeDisplay::minimum() const
121 {
122     return m_minimum;
123 }
124
125 int TimecodeDisplay::getValue() const
126 {
127     if (m_frametimecode) return lineedit->text().toInt();
128     else return m_timecode.getFrameCount(lineedit->text());
129 }
130
131 GenTime TimecodeDisplay::gentime() const
132 {
133     return GenTime(getValue(), m_timecode.fps());
134 }
135
136 Timecode TimecodeDisplay::timecode() const
137 {
138     return m_timecode;
139 }
140
141 void TimecodeDisplay::setRange(int min, int max)
142 {
143     m_minimum = min;
144     m_maximum = max;
145 }
146
147 void TimecodeDisplay::setValue(const QString &value)
148 {
149     setValue(m_timecode.getFrameCount(value));
150 }
151
152 void TimecodeDisplay::setValue(int value)
153 {
154     if (value < m_minimum)
155         value = m_minimum;
156     if (m_maximum > m_minimum && value > m_maximum)
157         value = m_maximum;
158
159     if (value == getValue() && !lineedit->text().isEmpty()) return;
160     downarrow->setEnabled(value > m_minimum);
161     uparrow->setEnabled(m_maximum < m_minimum || value < m_maximum);
162
163     if (m_frametimecode)
164         lineedit->setText(QString::number(value));
165     else {
166         QString v = m_timecode.getTimecodeFromFrames(value);
167         lineedit->setText(v);
168     }
169 }
170
171 void TimecodeDisplay::setValue(GenTime value)
172 {
173     setValue(m_timecode.getTimecode(value));
174 }
175
176 void TimecodeDisplay::slotCursorPositionChanged(int oldPos, int newPos)
177 {
178     lineedit->blockSignals(true);
179     QString text = lineedit->text();
180
181     if (newPos < text.size() && !text.at(newPos).isDigit()) {
182         // char at newPos is a separator (':' or ';')
183
184         // make it possible move the cursor backwards at separators
185         if (newPos == oldPos - 1)
186             lineedit->setSelection(newPos, -1);
187         else
188             lineedit->setSelection(newPos + 2, -1);
189     } else if (newPos < text.size()) {
190         lineedit->setSelection(newPos + 1, -1);
191     } else {
192         lineedit->setSelection(newPos, -1);
193     }
194
195     lineedit->blockSignals(false);
196 }
197
198 #include <timecodedisplay.moc>