File indexing completed on 2024-11-03 04:29:23
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 2010 Jean-Baptiste Mardelle <jb@kdenlive.org> 0003 0004 SPDX-License-Identifier: LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "timecodedisplay.h" 0008 #include "core.h" 0009 #include "kdenlivesettings.h" 0010 0011 #include <QFontDatabase> 0012 #include <QLineEdit> 0013 #include <QMouseEvent> 0014 #include <QStyle> 0015 0016 #include <KColorScheme> 0017 0018 TimecodeValidator::TimecodeValidator(QObject *parent) 0019 : QValidator(parent) 0020 { 0021 } 0022 0023 void TimecodeValidator::fixup(QString &str) const 0024 { 0025 str.replace(QLatin1Char(' '), QLatin1Char('0')); 0026 } 0027 0028 QValidator::State TimecodeValidator::validate(QString &str, int &) const 0029 { 0030 if (str.contains(QLatin1Char(' '))) { 0031 fixup(str); 0032 } 0033 return QValidator::Acceptable; 0034 } 0035 0036 TimecodeDisplay::TimecodeDisplay(QWidget *parent, bool autoAdjust) 0037 : TimecodeDisplay(parent, (pCore && autoAdjust) ? pCore->timecode() : Timecode()) 0038 { 0039 if (pCore && autoAdjust) { 0040 connect(pCore.get(), &Core::updateProjectTimecode, this, &TimecodeDisplay::refreshTimeCode); 0041 } 0042 } 0043 0044 TimecodeDisplay::TimecodeDisplay(QWidget *parent, const Timecode &t) 0045 : QAbstractSpinBox(parent) 0046 , m_timecode(t) 0047 , m_frametimecode(false) 0048 , m_minimum(0) 0049 , m_maximum(-1) 0050 , m_value(0) 0051 , m_offset(0) 0052 { 0053 const QFont ft = QFontDatabase::systemFont(QFontDatabase::FixedFont); 0054 lineEdit()->setFont(ft); 0055 setFont(ft); 0056 lineEdit()->setAlignment(Qt::AlignRight | Qt::AlignVCenter); 0057 QFontMetrics fm(ft); 0058 setFrame(false); 0059 QPalette palette; 0060 palette.setColor(QPalette::Base, Qt::transparent); // palette.window().color()); 0061 setPalette(palette); 0062 setTimeCodeFormat(KdenliveSettings::frametimecode(), true); 0063 setValue(m_minimum); 0064 setMinimumWidth(fm.horizontalAdvance(QStringLiteral("88:88:88:88")) + contentsMargins().right() + contentsMargins().left() + frameSize().width() - 0065 lineEdit()->contentsRect().width() + (int)QStyle::PM_SpinBoxFrameWidth + 6); 0066 0067 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Maximum); 0068 setAccelerated(true); 0069 connect(lineEdit(), &QLineEdit::editingFinished, this, &TimecodeDisplay::slotEditingFinished, Qt::DirectConnection); 0070 } 0071 0072 // virtual protected 0073 QAbstractSpinBox::StepEnabled TimecodeDisplay::stepEnabled() const 0074 { 0075 QAbstractSpinBox::StepEnabled result = QAbstractSpinBox::StepNone; 0076 if (m_value > m_minimum) { 0077 result |= QAbstractSpinBox::StepDownEnabled; 0078 } 0079 if (m_maximum == -1 || m_value < m_maximum) { 0080 result |= QAbstractSpinBox::StepUpEnabled; 0081 } 0082 return result; 0083 } 0084 0085 // virtual 0086 void TimecodeDisplay::stepBy(int steps) 0087 { 0088 int val = m_value + steps; 0089 setValue(val); 0090 } 0091 0092 void TimecodeDisplay::setTimeCodeFormat(bool frametimecode, bool init) 0093 { 0094 if (!init && m_frametimecode == frametimecode) { 0095 return; 0096 } 0097 m_frametimecode = frametimecode; 0098 lineEdit()->clear(); 0099 if (m_frametimecode) { 0100 auto *valid = new QIntValidator(lineEdit()); 0101 valid->setBottom(0); 0102 lineEdit()->setValidator(valid); 0103 lineEdit()->setInputMask(QString()); 0104 } else { 0105 lineEdit()->setInputMask(m_timecode.mask()); 0106 auto *valid = new TimecodeValidator(lineEdit()); 0107 lineEdit()->setValidator(valid); 0108 } 0109 setValue(m_value); 0110 } 0111 0112 void TimecodeDisplay::updateTimeCode(const Timecode &t) 0113 { 0114 m_timecode = t; 0115 setTimeCodeFormat(KdenliveSettings::frametimecode(), true); 0116 } 0117 0118 void TimecodeDisplay::refreshTimeCode() 0119 { 0120 updateTimeCode(pCore->timecode()); 0121 } 0122 0123 void TimecodeDisplay::keyPressEvent(QKeyEvent *e) 0124 { 0125 if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { 0126 e->setAccepted(true); 0127 clearFocus(); 0128 } else { 0129 QAbstractSpinBox::keyPressEvent(e); 0130 } 0131 } 0132 0133 void TimecodeDisplay::mouseReleaseEvent(QMouseEvent *e) 0134 { 0135 QAbstractSpinBox::mouseReleaseEvent(e); 0136 if (!lineEdit()->underMouse()) { 0137 clearFocus(); 0138 } 0139 } 0140 0141 void TimecodeDisplay::wheelEvent(QWheelEvent *e) 0142 { 0143 QAbstractSpinBox::wheelEvent(e); 0144 if (hasFocus()) { 0145 clearFocus(); 0146 } else { 0147 slotEditingFinished(); 0148 } 0149 } 0150 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 0151 void TimecodeDisplay::enterEvent(QEnterEvent *e) 0152 #else 0153 void TimecodeDisplay::enterEvent(QEvent *e) 0154 #endif 0155 { 0156 QAbstractSpinBox::enterEvent(e); 0157 setFrame(true); 0158 } 0159 0160 void TimecodeDisplay::leaveEvent(QEvent *e) 0161 { 0162 QAbstractSpinBox::leaveEvent(e); 0163 setFrame(false); 0164 } 0165 0166 int TimecodeDisplay::maximum() const 0167 { 0168 return m_maximum; 0169 } 0170 0171 int TimecodeDisplay::minimum() const 0172 { 0173 return m_minimum; 0174 } 0175 0176 int TimecodeDisplay::getValue() const 0177 { 0178 return m_value; 0179 } 0180 0181 GenTime TimecodeDisplay::gentime() const 0182 { 0183 return {m_value, m_timecode.fps()}; 0184 } 0185 0186 Timecode TimecodeDisplay::timecode() const 0187 { 0188 return m_timecode; 0189 } 0190 0191 void TimecodeDisplay::setTimecode(const Timecode &t) 0192 { 0193 m_timecode = t; 0194 } 0195 0196 void TimecodeDisplay::setRange(int min, int max) 0197 { 0198 m_minimum = min; 0199 m_maximum = max; 0200 } 0201 0202 void TimecodeDisplay::setValue(const QString &value) 0203 { 0204 setValue(m_timecode.getFrameCount(value)); 0205 } 0206 0207 void TimecodeDisplay::setValue(int value) 0208 { 0209 if (m_maximum > 0) { 0210 value = qBound(m_minimum, value, m_maximum); 0211 } else { 0212 value = qMax(m_minimum, value); 0213 } 0214 0215 if (m_frametimecode) { 0216 if (value == m_value && !lineEdit()->text().isEmpty()) { 0217 return; 0218 } 0219 m_value = value; 0220 lineEdit()->setText(QString::number(value - m_minimum)); 0221 } else { 0222 if (value == m_value && lineEdit()->text() != QLatin1String(":::")) { 0223 return; 0224 } 0225 m_value = value; 0226 lineEdit()->setText(m_timecode.getTimecodeFromFrames(m_offset + value - m_minimum)); 0227 } 0228 Q_EMIT timeCodeUpdated(); 0229 } 0230 0231 void TimecodeDisplay::setValue(const GenTime &value) 0232 { 0233 setValue((int)value.frames(m_timecode.fps())); 0234 } 0235 0236 void TimecodeDisplay::slotEditingFinished() 0237 { 0238 lineEdit()->deselect(); 0239 if (m_frametimecode) { 0240 setValue(lineEdit()->text().toInt() + m_minimum); 0241 } else { 0242 setValue(m_timecode.getFrameCount(lineEdit()->text()) + m_minimum - m_offset); 0243 } 0244 Q_EMIT timeCodeEditingFinished(m_value); 0245 } 0246 0247 const QString TimecodeDisplay::displayText() const 0248 { 0249 return lineEdit()->displayText(); 0250 } 0251 0252 void TimecodeDisplay::selectAll() 0253 { 0254 lineEdit()->selectAll(); 0255 } 0256 0257 void TimecodeDisplay::setOffset(int offset) 0258 { 0259 m_offset = GenTime(offset / 1000.).frames(m_timecode.fps()); 0260 // Update timecode display 0261 if (!m_frametimecode) { 0262 lineEdit()->setText(m_timecode.getTimecodeFromFrames(m_offset + m_value - m_minimum)); 0263 Q_EMIT timeCodeUpdated(); 0264 } 0265 }