Commit 75ad10ad authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle

Add clip length adjustment to speed dialog.

Related to #224
parent ec1ceb3e
......@@ -23,15 +23,19 @@
#include "speeddialog.h"
#include "ui_clipspeed_ui.h"
#include "effects/effectsrepository.hpp"
#include "timecodedisplay.h"
#include "core.h"
#include <QPushButton>
#include <QDebug>
#include <KMessageWidget>
#include <QtMath>
SpeedDialog::SpeedDialog(QWidget *parent, double speed, double minSpeed, double maxSpeed, bool reversed, bool pitch_compensate)
SpeedDialog::SpeedDialog(QWidget *parent, double speed, int duration, double minSpeed, double maxSpeed, bool reversed, bool pitch_compensate)
: QDialog(parent)
, ui(new Ui::ClipSpeed_UI)
, m_durationDisplay(nullptr)
, m_duration(duration)
{
ui->setupUi(this);
setWindowTitle(i18n("Clip Speed"));
......@@ -61,26 +65,64 @@ SpeedDialog::SpeedDialog(QWidget *parent, double speed, double minSpeed, double
infoMessage->hide();
ui->speedSpin->setFocus();
ui->speedSpin->selectAll();
if (m_duration > 0) {
ui->durationLayout->addWidget(new QLabel(i18n("Duration"), this));
m_durationDisplay = new TimecodeDisplay(pCore->timecode());
m_durationDisplay->setValue(m_duration);
ui->durationLayout->addWidget(m_durationDisplay);
connect(m_durationDisplay, &TimecodeDisplay::timeCodeEditingFinished, [this, infoMessage, speed, minSpeed](int value) {
if (value < 1) {
value = 1;
m_durationDisplay->setValue(value);
} else if (value > m_duration * speed / minSpeed) {
value = m_duration * speed / minSpeed;
m_durationDisplay->setValue(value);
}
double updatedSpeed = speed * m_duration / value;
QSignalBlocker bk(ui->speedSlider);
ui->speedSlider->setValue(qLn(updatedSpeed) * 12);
QSignalBlocker bk2(ui->speedSpin);
ui->speedSpin->setValue(updatedSpeed);
checkSpeed(infoMessage, updatedSpeed);
});
}
connect(ui->speedSpin, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [&] (double value) {
connect(ui->speedSpin, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [&, speed] (double value) {
QSignalBlocker bk(ui->speedSlider);
ui->speedSlider->setValue(qLn(value) * 12);
if (m_durationDisplay) {
QSignalBlocker bk2(m_durationDisplay);
int dur = qRound(m_duration * std::fabs(speed / value));
qDebug()<<"==== CALCULATED SPEED DIALOG DURATION: "<<dur;
m_durationDisplay->setValue(dur);
}
ui->buttonBox->button((QDialogButtonBox::Ok))->setEnabled(!qFuzzyIsNull(value));
});
connect(ui->speedSlider, &QSlider::valueChanged, [this, infoMessage] (int value) {
connect(ui->speedSlider, &QSlider::valueChanged, [this, infoMessage, speed] (int value) {
double res = qExp(value / 12.);
QSignalBlocker bk(ui->speedSpin);
if (res < ui->speedSpin->minimum() || res > ui->speedSpin->maximum()) {
infoMessage->setText(res < ui->speedSpin->minimum() ? i18n("Minimum speed is %1", ui->speedSpin->minimum()) : i18n("Maximum speed is %1", ui->speedSpin->maximum()));
infoMessage->setCloseButtonVisible(true);
infoMessage->setMessageType(KMessageWidget::Warning);
infoMessage->animatedShow();
}
checkSpeed(infoMessage, res);
ui->speedSpin->setValue(res);
if (m_durationDisplay) {
QSignalBlocker bk2(m_durationDisplay);
m_durationDisplay->setValue(qRound(m_duration * std::fabs(speed / res)));
}
ui->buttonBox->button((QDialogButtonBox::Ok))->setEnabled(!qFuzzyIsNull(ui->speedSpin->value()));
});
}
void SpeedDialog::checkSpeed(KMessageWidget *infoMessage, double res)
{
if (res < ui->speedSpin->minimum() || res > ui->speedSpin->maximum()) {
infoMessage->setText(res < ui->speedSpin->minimum() ? i18n("Minimum speed is %1", ui->speedSpin->minimum()) : i18n("Maximum speed is %1", ui->speedSpin->maximum()));
infoMessage->setCloseButtonVisible(true);
infoMessage->setMessageType(KMessageWidget::Warning);
infoMessage->animatedShow();
}
}
SpeedDialog::~SpeedDialog()
{
delete ui;
......
......@@ -28,12 +28,15 @@ namespace Ui {
class ClipSpeed_UI;
}
class TimecodeDisplay;
class KMessageWidget;
class SpeedDialog : public QDialog
{
Q_OBJECT
public:
explicit SpeedDialog(QWidget *parent, double speed, double minSpeed, double maxSpeed, bool reversed, bool pitch_compensate);
explicit SpeedDialog(QWidget *parent, double speed, int duration, double minSpeed, double maxSpeed, bool reversed, bool pitch_compensate);
~SpeedDialog();
double getValue() const;
......@@ -41,6 +44,9 @@ public:
private:
Ui::ClipSpeed_UI *ui;
TimecodeDisplay *m_durationDisplay;
int m_duration;
void checkSpeed(KMessageWidget *infoMessage, double res);
};
#endif // SPEEDDIALOG_H
......@@ -1897,11 +1897,11 @@ void TimelineController::changeItemSpeed(int clipId, double speed)
bool pitchCompensate = m_model->m_allClips[clipId]->getIntProperty(QStringLiteral("warp_pitch"));
if (qFuzzyCompare(speed, -1)) {
speed = 100 * m_model->getClipSpeed(clipId);
double duration = m_model->getItemPlaytime(clipId);
int duration = m_model->getItemPlaytime(clipId);
// this is the max speed so that the clip is at least one frame long
double maxSpeed = 100. * duration * qAbs(m_model->getClipSpeed(clipId));
double maxSpeed = duration * qAbs(speed);
// this is the min speed so that the clip doesn't bump into the next one on track
double minSpeed = 100. * duration * qAbs(m_model->getClipSpeed(clipId)) / (duration + double(m_model->getBlankSizeNearClip(clipId, true)));
double minSpeed = duration * qAbs(speed) / (duration + double(m_model->getBlankSizeNearClip(clipId, true)));
// if there is a split partner, we must also take it into account
int partner = m_model->getClipSplitPartner(clipId);
......@@ -1912,7 +1912,7 @@ void TimelineController::changeItemSpeed(int clipId, double speed)
minSpeed = std::max(minSpeed, minSpeed2);
maxSpeed = std::min(maxSpeed, maxSpeed2);
}
QScopedPointer<SpeedDialog> d(new SpeedDialog(QApplication::activeWindow(), std::abs(speed), minSpeed, maxSpeed, speed < 0, pitchCompensate));
QScopedPointer<SpeedDialog> d(new SpeedDialog(QApplication::activeWindow(), std::abs(speed), duration, minSpeed, maxSpeed, speed < 0, pitchCompensate));
if (d->exec() != QDialog::Accepted) {
return;
}
......
......@@ -14,28 +14,26 @@
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="6" column="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="3" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
<item row="0" column="0" colspan="3">
<layout class="QHBoxLayout" name="destination_layout">
<item>
<widget class="QLabel" name="label_dest">
<property name="text">
<string>Destination</string>
</property>
</widget>
</item>
<item>
<widget class="KUrlRequester" name="kurlrequester">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout">
......@@ -86,55 +84,57 @@
<property name="text">
<string>...</string>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0" colspan="3">
<item row="5" column="0" colspan="3">
<layout class="QHBoxLayout" name="infoLayout">
<property name="topMargin">
<number>0</number>
</property>
</layout>
</item>
<item row="0" column="0" colspan="3">
<layout class="QHBoxLayout" name="destination_layout">
<item>
<widget class="QLabel" name="label_dest">
<property name="text">
<string>Destination</string>
</property>
</widget>
</item>
<item>
<widget class="KUrlRequester" name="kurlrequester">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="pitchCompensate">
<property name="text">
<string>Pitch compensation</string>
<item row="7" column="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="2" column="2">
<item row="3" column="2">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Reverse clip</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="pitchCompensate">
<property name="text">
<string>Pitch compensation</string>
</property>
</widget>
</item>
<item row="4" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0" colspan="3">
<layout class="QHBoxLayout" name="durationLayout"/>
</item>
</layout>
</widget>
<customwidgets>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment