From cde668b5901bc9a7b9931bef2eb7005791aa41ed Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Wed, 18 Dec 2019 02:09:53 +1100 Subject: [PATCH] implemented percentage and decibel view modes for slider A slider can now hold a float value and display it in the UI converted to either a percentage or a decibel (still returning a linear float value programmatically for the rest of the code). --- app/widget/slider/floatslider.cpp | 100 +++++++++++++++++++++++++++++- app/widget/slider/floatslider.h | 13 ++++ app/widget/slider/sliderbase.cpp | 22 +++++-- app/widget/slider/sliderbase.h | 2 + app/widget/slider/sliderlabel.cpp | 4 +- 5 files changed, 131 insertions(+), 10 deletions(-) diff --git a/app/widget/slider/floatslider.cpp b/app/widget/slider/floatslider.cpp index 7d1dad694..36b33c3d7 100644 --- a/app/widget/slider/floatslider.cpp +++ b/app/widget/slider/floatslider.cpp @@ -20,8 +20,11 @@ #include "floatslider.h" +#include + FloatSlider::FloatSlider(QWidget *parent) : - SliderBase(kFloat, parent) + SliderBase(kFloat, parent), + display_type_(kNormal) { connect(this, SIGNAL(ValueChanged(QVariant)), this, SLOT(ConvertValue(QVariant))); } @@ -53,17 +56,108 @@ void FloatSlider::SetDecimalPlaces(int i) UpdateLabel(Value()); } +void FloatSlider::SetDisplayType(const FloatSlider::DisplayType &type) +{ + display_type_ = type; + + UpdateLabel(Value()); +} + QString FloatSlider::ValueToString(const QVariant &v) { - return QString::number(v.toDouble(), 'f', decimal_places_); + double val = v.toDouble(); + + switch (display_type_) { + case kNormal: + // Do nothing, skip to the return string at the end + break; + case kDecibel: + { + // Convert to decibels and return dB formatted string + qreal decibels = QAudio::convertVolume(val, QAudio::LinearVolumeScale, QAudio::DecibelVolumeScale); + return QStringLiteral("%1 dB").arg(QString::number(decibels, 'f', decimal_places_)); + } + case kPercentage: + // Multiply value by 100 for user-friendly percentage + val *= 100.0; + return QStringLiteral("%1%").arg(QString::number(val, 'f', decimal_places_)); + } + + return QString::number(val, 'f', decimal_places_); } QVariant FloatSlider::StringToValue(const QString &s, bool *ok) { - // Allow both floats and integers for either modes + switch (display_type_) { + case kNormal: + // Do nothing, skip to the return string at the end + break; + case kDecibel: + { + bool valid; + + // Remove any instance of "dB" in the string + QString decibel_number = s; + decibel_number.replace("dB", "", Qt::CaseInsensitive); + + // See if we can get a decimal number out of this + qreal decibels = decibel_number.toDouble(&valid); + + if (ok) *ok = valid; + + if (valid) { + // Convert from decibel scale to linear decimal + return QAudio::convertVolume(decibels, QAudio::DecibelVolumeScale, QAudio::LinearVolumeScale); + } + + break; + } + case kPercentage: + { + bool valid; + + QString percent_number = s; + percent_number.replace("%", "", Qt::CaseInsensitive); + + // Try to get double value + double val = percent_number.toDouble(&valid); + + if (ok) *ok = valid; + + // If we could get it, convert back to a 0.0 - 1.0 value and return + if (valid) { + return val * 0.01; + } + + break; + } + } + + // Just try to convert the string to a double return s.toDouble(ok); } +double FloatSlider::AdjustDragDistanceInternal(const double &start, const double &drag) +{ + switch (display_type_) { + case kNormal: + // No change here + break; + case kDecibel: + { + qreal current_db = QAudio::convertVolume(start, QAudio::LinearVolumeScale, QAudio::DecibelVolumeScale); + current_db += drag; + qreal adjusted_linear = QAudio::convertVolume(current_db, QAudio::DecibelVolumeScale, QAudio::LinearVolumeScale); + + return adjusted_linear - start; + } + case kPercentage: + return drag * 0.01; + } + + return SliderBase::AdjustDragDistanceInternal(start, drag); +} + void FloatSlider::ConvertValue(QVariant v) { emit ValueChanged(v.toDouble()); diff --git a/app/widget/slider/floatslider.h b/app/widget/slider/floatslider.h index 337c62310..56d43e88c 100644 --- a/app/widget/slider/floatslider.h +++ b/app/widget/slider/floatslider.h @@ -29,6 +29,12 @@ class FloatSlider : public SliderBase public: FloatSlider(QWidget* parent = nullptr); + enum DisplayType { + kNormal, + kDecibel, + kPercentage + }; + double GetValue(); void SetValue(const double& d); @@ -39,16 +45,23 @@ public: void SetDecimalPlaces(int i); + void SetDisplayType(const DisplayType& type); + 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(double); private slots: void ConvertValue(QVariant v); + +private: + DisplayType display_type_; }; #endif // FLOATSLIDER_H diff --git a/app/widget/slider/sliderbase.cpp b/app/widget/slider/sliderbase.cpp index 2ead1e203..d6ae769b1 100644 --- a/app/widget/slider/sliderbase.cpp +++ b/app/widget/slider/sliderbase.cpp @@ -162,6 +162,12 @@ void SliderBase::UpdateLabel(const QVariant &v) } } +double SliderBase::AdjustDragDistanceInternal(const double &start, const double &drag) +{ + Q_UNUSED(start) + return drag; +} + QString SliderBase::ValueToString(const QVariant &v) { return v.toString(); @@ -178,23 +184,25 @@ void SliderBase::LabelPressed() dragged_ = false; if (mode_ != kString) { - dragged_diff_ = value_.toDouble(); + dragged_diff_ = 0; } } void SliderBase::LabelClicked() { if (dragged_) { + double drag_val = value_.toDouble() + AdjustDragDistanceInternal(value_.toDouble(), dragged_diff_); + // This was a drag switch (mode_) { case kString: // No-op break; case kInteger: - SetValue(qRound(dragged_diff_)); + SetValue(qRound(drag_val)); break; case kFloat: - SetValue(dragged_diff_); + SetValue(drag_val); break; } } else { @@ -227,11 +235,13 @@ void SliderBase::LabelDragged(int i) dragged_diff_ += real_drag; + double drag_val = value_.toDouble() + AdjustDragDistanceInternal(value_.toDouble(), dragged_diff_); + // Update temporary value if (mode_ == kInteger) { - temp_dragged_value_ = qRound(dragged_diff_); + temp_dragged_value_ = qRound(drag_val); } else { - temp_dragged_value_ = dragged_diff_; + temp_dragged_value_ = drag_val; } temp_dragged_value_ = ClampValue(temp_dragged_value_); @@ -260,7 +270,7 @@ void SliderBase::LineEditConfirmed() setCurrentWidget(label_); emit ValueChanged(value_); - } else if (require_valid_input_) { + } else if (require_valid_input_ && !IsTristate()) { QMessageBox::critical(this, tr("Invalid Value"), tr("The entered value is not valid for this field."), diff --git a/app/widget/slider/sliderbase.h b/app/widget/slider/sliderbase.h index 70c12c310..85daf9106 100644 --- a/app/widget/slider/sliderbase.h +++ b/app/widget/slider/sliderbase.h @@ -61,6 +61,8 @@ protected: void UpdateLabel(const QVariant& v); + virtual double AdjustDragDistanceInternal(const double& start, const double& drag); + virtual QString ValueToString(const QVariant &v); virtual QVariant StringToValue(const QString& s, bool* ok); diff --git a/app/widget/slider/sliderlabel.cpp b/app/widget/slider/sliderlabel.cpp index b0f029730..dc53d505b 100644 --- a/app/widget/slider/sliderlabel.cpp +++ b/app/widget/slider/sliderlabel.cpp @@ -78,5 +78,7 @@ void SliderLabel::focusInEvent(QFocusEvent *event) { QWidget::focusInEvent(event); - emit focused(); + if (event->reason() == Qt::TabFocusReason) { + emit focused(); + } }