diff --git a/app/widget/slider/CMakeLists.txt b/app/widget/slider/CMakeLists.txt
index ef2b3443c..0d9d22944 100644
--- a/app/widget/slider/CMakeLists.txt
+++ b/app/widget/slider/CMakeLists.txt
@@ -20,6 +20,8 @@ set(OLIVE_SOURCES
widget/slider/floatslider.cpp
widget/slider/integerslider.h
widget/slider/integerslider.cpp
+ widget/slider/rationalslider.h
+ widget/slider/rationalslider.cpp
widget/slider/sliderbase.h
widget/slider/sliderbase.cpp
widget/slider/sliderlabel.h
diff --git a/app/widget/slider/rationalslider.cpp b/app/widget/slider/rationalslider.cpp
new file mode 100644
index 000000000..a2650207e
--- /dev/null
+++ b/app/widget/slider/rationalslider.cpp
@@ -0,0 +1,142 @@
+/***
+ Olive - Non-Linear Video Editor
+ Copyright (C) 2020 Olive Team
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+***/
+
+#include "rationalslider.h"
+
+#include "common/timecodefunctions.h"
+#include "core.h"
+
+namespace olive {
+
+RationalSlider::RationalSlider(rational timebase, QWidget *parent) :
+ SliderBase(SliderBase::kRational, parent),
+ display_type_(kTimecode),
+ decimal_places_(2),
+ autotrim_decimal_places_(false),
+ timebase_(timebase)
+{
+ connect(this, SIGNAL(ValueChanged(QVariant)), this, SLOT(ConvertValue(QVariant)));
+}
+
+rational RationalSlider::GetValue()
+{
+ return Value().value();
+}
+
+void RationalSlider::SetValue(const rational &d)
+{
+ QVariant r;
+ r.setValue(d);
+ SliderBase::SetValue(r);
+}
+
+void RationalSlider::SetMinimum(const rational &d)
+{
+ QVariant r;
+ r.setValue(d);
+ SetMinimumInternal(r);
+}
+
+void RationalSlider::SetMaximum(const rational &d)
+{
+ QVariant r;
+ r.setValue(d);
+ SetMaximumInternal(r);
+}
+
+void RationalSlider::SetDecimalPlaces(int i)
+{
+ decimal_places_ = i;
+
+ ForceLabelUpdate();
+}
+
+void RationalSlider::SetTimebase(const rational &timebase)
+{
+ timebase_ = timebase;
+
+ // Refresh label since we have a new timebase to generate a timecode with
+ UpdateLabel(Value());
+}
+
+void RationalSlider::SetAutoTrimDecimalPlaces(bool e) {
+ autotrim_decimal_places_ = e;
+
+ ForceLabelUpdate();
+}
+
+void RationalSlider::SetDisplayType(const RationalSlider::DisplayType &type)
+{
+ display_type_ = type;
+
+ switch (display_type_) {
+ case kTimecode:
+ case kRational:
+ ClearFormat();
+ break;
+ case kTimestamp:
+ SetFormat("%1 Frames");
+ break;
+ case kFloat:
+ SetFormat("%1 Seconds");
+ break;
+ }
+}
+
+QString RationalSlider::ValueToString(const QVariant &v)
+{
+ rational r = v.value();
+ switch (display_type_) {
+ case kTimecode:
+ return Timecode::time_to_timecode(r, timebase_, Core::instance()->GetTimecodeDisplay());
+ case kTimestamp:
+ return QString::number(Timecode::time_to_timestamp(r, timebase_));
+ case kRational:
+ // Might we want to call reduce() on r here?
+ return r.toString();
+ case kFloat:
+ {
+ QString s = QString::number(r.toDouble(), 'f', decimal_places_);
+
+ if (autotrim_decimal_places_) {
+ while (s.endsWith('0') && s.at(s.size() - 2).isDigit()) {
+ s = s.left(s.size() - 1);
+ }
+ }
+ return s;
+ }
+ }
+ return r.toString();
+}
+
+QVariant RationalSlider::StringToValue(const QString &s, bool *ok)
+{
+ // Just try to convert the string to a double
+ // REMEMBER TO IMPLEMENT!!!!
+ return s.toDouble(ok);
+}
+
+double RationalSlider::AdjustDragDistanceInternal(const double &start, const double &drag)
+{
+ // Assume we want smallest increment to be timebase or 1 frame
+ return start + drag*timebase_.toDouble();
+}
+
+void RationalSlider::ConvertValue(QVariant v)
+{
+ emit ValueChanged(v.value());
+}
+
+}
diff --git a/app/widget/slider/rationalslider.h b/app/widget/slider/rationalslider.h
new file mode 100644
index 000000000..916b06513
--- /dev/null
+++ b/app/widget/slider/rationalslider.h
@@ -0,0 +1,80 @@
+/***
+ Olive - Non-Linear Video Editor
+ Copyright (C) 2020 Olive Team
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+***/
+
+#ifndef RATIONALSLIDER_H
+#define RATIONALSLIDER_H
+
+#include "sliderbase.h"
+
+#include "common/rational.h"
+
+namespace olive {
+
+class RationalSlider : public SliderBase
+{
+ Q_OBJECT
+public:
+ RationalSlider(QWidget* parent = nullptr);
+
+ enum DisplayType {
+ kTimecode,
+ kTimestamp,
+ kRational,
+ kFloat
+ };
+
+ rational GetValue();
+
+ void SetValue(const rational& d);
+
+ void SetMinimum(const rational& d);
+
+ void SetMaximum(const rational& d);
+
+ void SetDecimalPlaces(int i);
+
+ void SetTimebase(const rational& timebase);
+
+ void SetDisplayType(const DisplayType& type);
+
+ void SetAutoTrimDecimalPlaces(bool e);
+
+protected:
+ virtual QString ValueToString(const QVariant& v) override;
+
+ virtual QVariant StringToValue(const QString& s, bool* ok) override;
+
+ virtual double AdjustDragDistanceInternal(const double& start, const double& drag) override;
+
+signals:
+ void ValueChanged(rational);
+
+private slots:
+ void ConvertValue(QVariant v);
+
+private:
+ DisplayType display_type_;
+
+ int decimal_places_;
+
+ bool autotrim_decimal_places_;
+
+ rational timebase_;
+
+};
+
+}
+
+#endif // RATIONALSLIDER_H
diff --git a/app/widget/slider/sliderbase.cpp b/app/widget/slider/sliderbase.cpp
index 25d36f10b..5d1781b27 100644
--- a/app/widget/slider/sliderbase.cpp
+++ b/app/widget/slider/sliderbase.cpp
@@ -65,6 +65,7 @@ SliderBase::SliderBase(Mode mode, QWidget *parent) :
break;
case kInteger:
case kFloat:
+ case kRational:
setCursor(Qt::SizeHorCursor);
break;
}
@@ -276,6 +277,7 @@ void SliderBase::LadderDragged(int value, double multiplier)
break;
case kInteger:
case kFloat:
+ case kRational:
{
dragged_diff_ += value * drag_multiplier_ * multiplier;
@@ -322,6 +324,10 @@ void SliderBase::LadderReleased()
case kFloat:
SetValue(clamped_temp_dragged_value_.toDouble());
break;
+ case kRational:
+ QVariant r;
+ r.setValue(rational(temp_dragged_value_.toDouble()));
+ SetValue(r);
}
emit ValueChanged(value_);
diff --git a/app/widget/slider/sliderbase.h b/app/widget/slider/sliderbase.h
index 5d5a9fc95..19d7dd897 100644
--- a/app/widget/slider/sliderbase.h
+++ b/app/widget/slider/sliderbase.h
@@ -35,7 +35,8 @@ public:
enum Mode {
kString,
kInteger,
- kFloat
+ kFloat,
+ kRational
};
SliderBase(Mode mode, QWidget* parent = nullptr);