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