]> git.sesse.net Git - kdenlive/blob - src/timecodedisplay.cpp
* Cleanup timecode display widget
[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 #include <krestrictedline.h>
31 #include <KColorScheme>
32 #include <KRestrictedLine>
33
34 TimecodeDisplay::TimecodeDisplay(Timecode t, QWidget *parent)
35         : QAbstractSpinBox(parent),
36         m_timecode(t),
37         m_minimum(0),
38         m_maximum(-1)
39 {
40     lineEdit()->setFont(KGlobalSettings::toolBarFont());
41     lineEdit()->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
42     QFontMetrics fm = lineEdit()->fontMetrics();
43     setMinimumWidth(fm.width("88:88:88:88888888") + contentsMargins().right() + contentsMargins().right());
44     setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
45     setAccelerated(true);
46
47     setTimeCodeFormat(KdenliveSettings::frametimecode(), true);
48
49     connect(lineEdit(), SIGNAL(returnPressed()), this, SLOT(slotEditingFinished()));
50     connect(lineEdit(), SIGNAL(cursorPositionChanged(int, int)), this, SLOT(slotCursorPositionChanged(int, int)));
51 }
52
53 // virtual protected
54 QAbstractSpinBox::StepEnabled TimecodeDisplay::stepEnabled () const
55 {
56     QAbstractSpinBox::StepEnabled result = QAbstractSpinBox::StepNone;
57     if (getValue() > m_minimum) result |= QAbstractSpinBox::StepDownEnabled;
58     if (m_maximum == -1 || getValue() < m_maximum) result |= QAbstractSpinBox::StepUpEnabled;
59     return result;
60 }
61
62 // virtual
63 void TimecodeDisplay::stepBy(int steps)
64 {
65     int val = getValue();
66     val += steps;
67     setValue(val);
68     emit editingFinished();
69 }
70
71 void TimecodeDisplay::setTimeCodeFormat(bool frametimecode, bool init)
72 {
73     if (!init && m_frametimecode == frametimecode) return;
74     int val = getValue();
75     m_frametimecode = frametimecode;
76     if (m_frametimecode) {
77         QIntValidator *valid = new QIntValidator(lineEdit());
78         valid->setBottom(0);
79         lineEdit()->setValidator(valid);
80     } else {
81         lineEdit()->setValidator(m_timecode.validator());
82     }
83     setValue(val);
84 }
85
86 void TimecodeDisplay::slotUpdateTimeCodeFormat()
87 {
88     setTimeCodeFormat(KdenliveSettings::frametimecode());
89 }
90
91 void TimecodeDisplay::updateTimeCode(Timecode t)
92 {
93     m_timecode = t;
94     setTimeCodeFormat(KdenliveSettings::frametimecode());
95 }
96
97 void TimecodeDisplay::keyPressEvent(QKeyEvent *e)
98 {
99     if (e->key() == Qt::Key_Return)
100         slotEditingFinished();
101     else
102         QAbstractSpinBox::keyPressEvent(e);
103 }
104
105 void TimecodeDisplay::mouseReleaseEvent(QMouseEvent *e)
106 {
107     QAbstractSpinBox::mouseReleaseEvent(e);
108     if (!lineEdit()->underMouse()) {
109         clearFocus();
110     }
111 }
112
113 /*
114 void TimecodeDisplay::wheelEvent(QWheelEvent *e)
115 {
116     if (e->delta() > 0)
117         slotValueUp();
118     else
119         slotValueDown();
120 }*/
121
122
123 int TimecodeDisplay::maximum() const
124 {
125     return m_maximum;
126 }
127
128 int TimecodeDisplay::minimum() const
129 {
130     return m_minimum;
131 }
132
133 int TimecodeDisplay::getValue() const
134 {
135     if (m_frametimecode) return lineEdit()->text().toInt();
136     else return m_timecode.getFrameCount(lineEdit()->text());
137 }
138
139 GenTime TimecodeDisplay::gentime() const
140 {
141     return GenTime(getValue(), m_timecode.fps());
142 }
143
144 Timecode TimecodeDisplay::timecode() const
145 {
146     return m_timecode;
147 }
148
149 void TimecodeDisplay::setRange(int min, int max)
150 {
151     m_minimum = min;
152     m_maximum = max;
153 }
154
155 void TimecodeDisplay::setValue(const QString &value)
156 {
157     setValue(m_timecode.getFrameCount(value));
158 }
159
160 void TimecodeDisplay::setValue(int value)
161 {
162     if (value < m_minimum)
163         value = m_minimum;
164     if (m_maximum > m_minimum && value > m_maximum)
165         value = m_maximum;
166
167     if (value == getValue() && !lineEdit()->text().isEmpty()) return;
168     //downarrow->setEnabled(value > m_minimum);
169     //uparrow->setEnabled(m_maximum < m_minimum || value < m_maximum);
170
171     if (m_frametimecode)
172         lineEdit()->setText(QString::number(value));
173     else {
174         QString v = m_timecode.getTimecodeFromFrames(value);
175         lineEdit()->setText(v);
176     }
177 }
178
179 void TimecodeDisplay::setValue(GenTime value)
180 {
181     setValue(m_timecode.getTimecode(value));
182 }
183
184 void TimecodeDisplay::slotCursorPositionChanged(int oldPos, int newPos)
185 {
186     if (!lineEdit()->hasFocus()) return;
187     lineEdit()->blockSignals(true);
188     QString text = lineEdit()->text();
189
190     if (newPos < text.size() && !text.at(newPos).isDigit()) {
191         // char at newPos is a separator (':' or ';')
192
193         // make it possible move the cursor backwards at separators
194         if (newPos == oldPos - 1)
195             lineEdit()->setSelection(newPos, -1);
196         else
197             lineEdit()->setSelection(newPos + 2, -1);
198     } else if (newPos < text.size()) {
199         lineEdit()->setSelection(newPos + 1, -1);
200     } else {
201         lineEdit()->setSelection(newPos, -1);
202     }
203
204     lineEdit()->blockSignals(false);
205 }
206
207 void TimecodeDisplay::slotEditingFinished()
208 {
209     clearFocus();
210     lineEdit()->deselect();
211     emit editingFinished();
212 }
213
214 #include <timecodedisplay.moc>