From 3bc26f6ce0cf67b6ff0d0ac379ba4316339dcddb Mon Sep 17 00:00:00 2001 From: Thomas Wilshaw Date: Thu, 17 Dec 2020 14:55:10 +0000 Subject: [PATCH] Finish implementation --- .../sequence/sequencedialogparametertab.cpp | 2 + app/widget/slider/rationalslider.cpp | 66 +++++++++++++--- app/widget/slider/rationalslider.h | 45 ++++++++++- app/widget/slider/sliderbase.cpp | 77 ++++++++++++++++--- app/widget/slider/sliderbase.h | 3 + app/widget/slider/sliderlabel.cpp | 4 +- app/widget/slider/sliderlabel.h | 2 + 7 files changed, 174 insertions(+), 25 deletions(-) diff --git a/app/dialog/sequence/sequencedialogparametertab.cpp b/app/dialog/sequence/sequencedialogparametertab.cpp index 2617cae4c..143b4a924 100644 --- a/app/dialog/sequence/sequencedialogparametertab.cpp +++ b/app/dialog/sequence/sequencedialogparametertab.cpp @@ -7,6 +7,8 @@ #include "core.h" +#include "widget//slider/rationalslider.h" + namespace olive { SequenceDialogParameterTab::SequenceDialogParameterTab(Sequence* sequence, QWidget* parent) : diff --git a/app/widget/slider/rationalslider.cpp b/app/widget/slider/rationalslider.cpp index a2650207e..b24d99725 100644 --- a/app/widget/slider/rationalslider.cpp +++ b/app/widget/slider/rationalslider.cpp @@ -20,14 +20,18 @@ namespace olive { -RationalSlider::RationalSlider(rational timebase, QWidget *parent) : +RationalSlider::RationalSlider(DisplayType display_type, rational timebase, QWidget *parent) : SliderBase(SliderBase::kRational, parent), - display_type_(kTimecode), + display_type_(display_type), decimal_places_(2), autotrim_decimal_places_(false), timebase_(timebase) { connect(this, SIGNAL(ValueChanged(QVariant)), this, SLOT(ConvertValue(QVariant))); + connect(this, &SliderBase::changeRationalDisplayType, this, &RationalSlider::changeDisplayType); + connect(Core::instance(), &Core::TimecodeDisplayChanged, this, &RationalSlider::ChangeTimecodeDisplayType); + + SetDisplayType(display_type_); } rational RationalSlider::GetValue() @@ -90,25 +94,26 @@ void RationalSlider::SetDisplayType(const RationalSlider::DisplayType &type) SetFormat("%1 Frames"); break; case kFloat: - SetFormat("%1 Seconds"); + SetFormat("%1 s"); break; } } QString RationalSlider::ValueToString(const QVariant &v) { - rational r = v.value(); + double time = v.value().toDouble(); + switch (display_type_) { case kTimecode: - return Timecode::time_to_timecode(r, timebase_, Core::instance()->GetTimecodeDisplay()); + return Timecode::time_to_timecode(v.value(), timebase_, Core::instance()->GetTimecodeDisplay()); case kTimestamp: - return QString::number(Timecode::time_to_timestamp(r, timebase_)); + return QString::number(Timecode::time_to_timestamp(time, timebase_)); case kRational: // Might we want to call reduce() on r here? - return r.toString(); + return v.value().toString(); case kFloat: { - QString s = QString::number(r.toDouble(), 'f', decimal_places_); + QString s = QString::number(time, 'f', decimal_places_); if (autotrim_decimal_places_) { while (s.endsWith('0') && s.at(s.size() - 2).isDigit()) { @@ -118,14 +123,40 @@ QString RationalSlider::ValueToString(const QVariant &v) return s; } } - return r.toString(); + return v.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); + QVariant v; + rational r; + *ok = false; + + switch (display_type_) { + case kTimecode: + { + int t = Timecode::timecode_to_timestamp(s, timebase_, Core::instance()->GetTimecodeDisplay(), ok); + r = rational(t, timebase_.denominator()); + break; + } + case kTimestamp: + r = rational(s.toInt(ok), timebase_.denominator()); + break; + case kRational: + r = rational::fromString(s); + if (!r.isNull()) { + *ok = true; + } + break; + case kFloat: + r = rational::fromDouble(s.toDouble(ok)); + if (!r.isNull()) { + *ok = true; + } + break; + } + v.setValue(r); + return v; } double RationalSlider::AdjustDragDistanceInternal(const double &start, const double &drag) @@ -139,4 +170,15 @@ void RationalSlider::ConvertValue(QVariant v) emit ValueChanged(v.value()); } +void RationalSlider::changeDisplayType() +{ + SetDisplayType(static_cast(((int)(display_type_)+1)%4)); + ForceLabelUpdate(); +} + +void RationalSlider::ChangeTimecodeDisplayType() +{ + ForceLabelUpdate(); +} + } diff --git a/app/widget/slider/rationalslider.h b/app/widget/slider/rationalslider.h index 916b06513..220bf2b44 100644 --- a/app/widget/slider/rationalslider.h +++ b/app/widget/slider/rationalslider.h @@ -18,16 +18,27 @@ #include "sliderbase.h" +#include + #include "common/rational.h" namespace olive { + /** + * @brief A olive::rational based slider + * + * A slider that can display rationals as either timecode, a timestamp (frames), a rational (a/b) + * or a float (seconds). + * + * Control clikcing the slider (see sliderlabel.h) changes thedisplay type + */ class RationalSlider : public SliderBase { Q_OBJECT public: - RationalSlider(QWidget* parent = nullptr); - + /** + * @brief enum containing the possibly display types + */ enum DisplayType { kTimecode, kTimestamp, @@ -35,18 +46,41 @@ public: kFloat }; + RationalSlider(DisplayType display_type, rational timebase, QWidget* parent = nullptr); + + /** + * @brief Returns the sliders value as a rational + */ rational GetValue(); + /** + * @brief Sets the sliders value + */ void SetValue(const rational& d); + /** + * @brief Sets the sliders minimum value + */ void SetMinimum(const rational& d); + /** + * @brief Sets the sliders maximum value + */ void SetMaximum(const rational& d); + /** + * @brief Sets the number of decimal places the slider shows when displaying a float + */ void SetDecimalPlaces(int i); + /** + * @brief Sets the sliders timebase which is also the minimum increment of the slider + */ void SetTimebase(const rational& timebase); + /** + * @brief Sets the display type of the slider + */ void SetDisplayType(const DisplayType& type); void SetAutoTrimDecimalPlaces(bool e); @@ -64,6 +98,13 @@ signals: private slots: void ConvertValue(QVariant v); + void changeDisplayType(); + + /** + * @brief Changes the timecodes display type (e.g. drop frome to none drop frame) + */ + void ChangeTimecodeDisplayType(); + private: DisplayType display_type_; diff --git a/app/widget/slider/sliderbase.cpp b/app/widget/slider/sliderbase.cpp index 5d1781b27..32b926909 100644 --- a/app/widget/slider/sliderbase.cpp +++ b/app/widget/slider/sliderbase.cpp @@ -55,6 +55,7 @@ SliderBase::SliderBase(Mode mode, QWidget *parent) : connect(label_, &SliderLabel::LabelPressed, this, &SliderBase::LabelPressed); connect(label_, &SliderLabel::focused, this, &SliderBase::ShowEditor); connect(label_, &SliderLabel::RequestReset, this, &SliderBase::ResetValue); + connect(label_, &SliderLabel::ChangeSliderType, this, &SliderBase::ChangeSliderType); connect(editor_, &FocusableLineEdit::Confirmed, this, &SliderBase::LineEditConfirmed); connect(editor_, &FocusableLineEdit::Cancelled, this, &SliderBase::LineEditCancelled); @@ -160,8 +161,14 @@ void SliderBase::SetMinimumInternal(const QVariant &v) has_min_ = true; // Limit value by this new minimum value - if (value_.toDouble() < min_value_.toDouble()) { - SetValue(min_value_); + if (mode_ == kRational) { + if (value_.value().toDouble() < min_value_.value().toDouble()) { + SetValue(min_value_); + } + } else { + if (value_.toDouble() < min_value_.toDouble()) { + SetValue(min_value_); + } } } @@ -171,8 +178,14 @@ void SliderBase::SetMaximumInternal(const QVariant &v) has_max_ = true; // Limit value by this new maximum value - if (value_.toDouble() > max_value_.toDouble()) { - SetValue(max_value_); + if (mode_ == kRational) { + if (value_.value().toDouble() > max_value_.value().toDouble()) { + SetValue(max_value_); + } + } else { + if (value_.toDouble() > max_value_.toDouble()) { + SetValue(max_value_); + } } } @@ -186,11 +199,22 @@ void SliderBase::changeEvent(QEvent *e) const QVariant &SliderBase::ClampValue(const QVariant &v) { - if (has_min_ && v.toDouble() < min_value_.toDouble()) { - return min_value_; + double value, min, max; + + if (mode_ == kRational) { + value = v.value().toDouble(); + min = min_value_.value().toDouble(); + max = max_value_.value().toDouble(); + } else { + value = v.toDouble(); + min = min_value_.toDouble(); + max = max_value_.toDouble(); } - - if (has_max_ && v.toDouble() > max_value_.toDouble()) { + + if (has_min_ && value < min) { + return min_value_; + }else if (has_max_ && value > max) { + printf("MAX: %f\n", max_value_.value().toDouble()); return max_value_; } @@ -253,6 +277,7 @@ void SliderBase::LabelPressed() break; case kInteger: case kFloat: + case kRational: { drag_ladder_ = new SliderLadder(drag_multiplier_, ladder_element_count_); drag_ladder_->SetValue(ValueToString(value_)); @@ -277,7 +302,6 @@ void SliderBase::LadderDragged(int value, double multiplier) break; case kInteger: case kFloat: - case kRational: { dragged_diff_ += value * drag_multiplier_ * multiplier; @@ -303,6 +327,32 @@ void SliderBase::LadderDragged(int value, double multiplier) emit ValueChanged(clamped_temp_dragged_value_); break; } + + case kRational: + { + double old_dragged_diff = dragged_diff_; + dragged_diff_ += value * drag_multiplier_ * multiplier; + + double drag_val = AdjustDragDistanceInternal(value_.value().toDouble(), dragged_diff_); + + rational d_v; + d_v = rational::fromDouble(drag_val); + temp_dragged_value_.setValue(d_v); + + QVariant clamped = ClampValue(temp_dragged_value_); + if (clamped.value() != temp_dragged_value_.value()) { + temp_dragged_value_ = clamped; + dragged_diff_ = old_dragged_diff; + } + + UpdateLabel(temp_dragged_value_); + + drag_ladder_->SetValue(ValueToString(temp_dragged_value_)); + RepositionLadder(); + + emit ValueChanged(temp_dragged_value_); + break; + } } } @@ -326,7 +376,7 @@ void SliderBase::LadderReleased() break; case kRational: QVariant r; - r.setValue(rational(temp_dragged_value_.toDouble())); + r.setValue(rational::fromDouble(temp_dragged_value_.value().toDouble())); SetValue(r); } @@ -407,4 +457,11 @@ void SliderBase::RepositionLadder() } } +void SliderBase::ChangeSliderType() +{ + if (mode_ == kRational) { + emit changeRationalDisplayType(); + } +} + } diff --git a/app/widget/slider/sliderbase.h b/app/widget/slider/sliderbase.h index 19d7dd897..c28fc48a7 100644 --- a/app/widget/slider/sliderbase.h +++ b/app/widget/slider/sliderbase.h @@ -72,6 +72,8 @@ public: signals: void ValueChanged(QVariant v); + void changeRationalDisplayType(); + protected: const QVariant& Value() const; @@ -151,6 +153,7 @@ private slots: void RepositionLadder(); + void ChangeSliderType(); }; } diff --git a/app/widget/slider/sliderlabel.cpp b/app/widget/slider/sliderlabel.cpp index 11048658f..2d4de040b 100644 --- a/app/widget/slider/sliderlabel.cpp +++ b/app/widget/slider/sliderlabel.cpp @@ -54,7 +54,9 @@ void SliderLabel::mousePressEvent(QMouseEvent *e) if (e->button() == Qt::LeftButton) { if (e->modifiers() & Qt::AltModifier) { emit RequestReset(); - } else { + } else if (e->modifiers() & Qt::ControlModifier) { + emit ChangeSliderType(); + } else { emit LabelPressed(); } } diff --git a/app/widget/slider/sliderlabel.h b/app/widget/slider/sliderlabel.h index 2f698eb2c..533208a3b 100644 --- a/app/widget/slider/sliderlabel.h +++ b/app/widget/slider/sliderlabel.h @@ -45,6 +45,8 @@ signals: void RequestReset(); + void ChangeSliderType(); + }; }