slider: reworked sliderbase and derivatives

Mostly cleaning up code, SliderBase was fairly messy.
This commit is contained in:
itsmattkc
2021-04-17 12:49:21 +10:00
parent f1d325629a
commit 9328539373
38 changed files with 1068 additions and 855 deletions
+26 -7
View File
@@ -5,23 +5,42 @@
namespace olive { namespace olive {
rational rational::fromDouble(const double &flt) rational rational::fromDouble(const double &flt, bool* ok)
{ {
// Use FFmpeg function for the time being // Use FFmpeg function for the time being
return av_d2q(flt, INT_MAX); AVRational r = av_d2q(flt, INT_MAX);
if (r.den == 0) {
// If den == 0, we were unable to convert to a rational
if (ok) {
*ok = false;
}
return rational();
} else {
// Otherwise, assume we received a real rational
if (ok) {
*ok = true;
}
return r;
}
} }
rational rational::fromString(const QString &str) rational rational::fromString(const QString &str, bool* ok)
{ {
QStringList elements = str.split('/'); QStringList elements = str.split('/');
switch (elements.size()) { switch (elements.size()) {
case 0:
return rational();
case 1: case 1:
return rational(elements.first().toLongLong()); return rational(elements.first().toLongLong(ok));
case 2:
return rational(elements.at(0).toLongLong(ok), elements.at(1).toLongLong(ok));
default: default:
return rational(elements.at(0).toLongLong(), elements.at(1).toLongLong()); if (ok) {
*ok = false;
}
return rational();
} }
} }
+2 -2
View File
@@ -61,9 +61,9 @@ public:
reduce(); reduce();
} }
static rational fromDouble(const double& flt); static rational fromDouble(const double& flt, bool *ok = nullptr);
static rational fromString(const QString& str); static rational fromString(const QString& str, bool* ok = nullptr);
//Assignment Operators //Assignment Operators
const rational& operator=(const rational &rhs); const rational& operator=(const rational &rhs);
+6
View File
@@ -233,6 +233,12 @@ err_fatal:
return 0; return 0;
} }
rational Timecode::timecode_to_time(const QString &timecode, const rational &timebase, const Timecode::Display &display, bool *ok)
{
int64_t timestamp = timecode_to_timestamp(timecode, timebase, display, ok);
return timestamp_to_time(timestamp, timebase);
}
rational Timecode::snap_time_to_timebase(const rational &time, const rational &timebase) rational Timecode::snap_time_to_timebase(const rational &time, const rational &timebase)
{ {
// Just convert to a timestamp in timebase units and back // Just convert to a timestamp in timebase units and back
+1
View File
@@ -53,6 +53,7 @@ public:
static QString timestamp_to_timecode(const int64_t &timestamp, const rational& timebase, const Display &display, bool show_plus_if_positive = false); static QString timestamp_to_timecode(const int64_t &timestamp, const rational& timebase, const Display &display, bool show_plus_if_positive = false);
static int64_t timecode_to_timestamp(const QString& timecode, const rational& timebase, const Display& display, bool *ok = nullptr); static int64_t timecode_to_timestamp(const QString& timecode, const rational& timebase, const Display& display, bool *ok = nullptr);
static rational timecode_to_time(const QString& timecode, const rational& timebase, const Display& display, bool *ok = nullptr);
static rational snap_time_to_timebase(const rational& time, const rational& timebase); static rational snap_time_to_timebase(const rational& time, const rational& timebase);
@@ -101,10 +101,11 @@ PreferencesGeneralTab::PreferencesGeneralTab()
timeline_layout->addWidget(new QLabel(tr("Default Still Image Length:")), row, 0); timeline_layout->addWidget(new QLabel(tr("Default Still Image Length:")), row, 0);
default_still_length_ = new FloatSlider(); default_still_length_ = new RationalSlider();
default_still_length_->SetMinimum(0.1); default_still_length_->SetMinimum(rational(100, 1000));
default_still_length_->SetTimebase(rational(100, 1000));
default_still_length_->SetFormat(tr("%1 seconds")); default_still_length_->SetFormat(tr("%1 seconds"));
default_still_length_->SetValue(Config::Current()["DefaultStillLength"].value<rational>().toDouble()); default_still_length_->SetValue(Config::Current()["DefaultStillLength"].value<rational>());
timeline_layout->addWidget(default_still_length_); timeline_layout->addWidget(default_still_length_);
row++; row++;
@@ -168,7 +169,7 @@ void PreferencesGeneralTab::Accept(MultiUndoCommand *command)
Config::Current()[QStringLiteral("Autoscroll")] = autoscroll_method_->currentData(); Config::Current()[QStringLiteral("Autoscroll")] = autoscroll_method_->currentData();
Config::Current()[QStringLiteral("DefaultStillLength")] = QVariant::fromValue(rational::fromDouble(default_still_length_->GetValue())); Config::Current()[QStringLiteral("DefaultStillLength")] = QVariant::fromValue(default_still_length_->GetValue());
QString set_language = language_combobox_->currentData().toString(); QString set_language = language_combobox_->currentData().toString();
if (QLocale::system().name() == set_language) { if (QLocale::system().name() == set_language) {
@@ -27,7 +27,7 @@
#include "dialog/configbase/configdialogbase.h" #include "dialog/configbase/configdialogbase.h"
#include "node/project/sequence/sequence.h" #include "node/project/sequence/sequence.h"
#include "widget/slider/floatslider.h" #include "widget/slider/rationalslider.h"
#include "widget/slider/integerslider.h" #include "widget/slider/integerslider.h"
namespace olive { namespace olive {
@@ -49,7 +49,7 @@ private:
QCheckBox* rectified_waveforms_; QCheckBox* rectified_waveforms_;
FloatSlider* default_still_length_; RationalSlider* default_still_length_;
QCheckBox* autorecovery_enabled_; QCheckBox* autorecovery_enabled_;
+6 -1
View File
@@ -25,6 +25,7 @@
#include "node/output/track/track.h" #include "node/output/track/track.h"
#include "transition/transition.h" #include "transition/transition.h"
#include "widget/slider/floatslider.h" #include "widget/slider/floatslider.h"
#include "widget/slider/rationalslider.h"
namespace olive { namespace olive {
@@ -43,11 +44,15 @@ Block::Block() :
out_transition_(nullptr) out_transition_(nullptr)
{ {
AddInput(kLengthInput, NodeValue::kRational, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable)); AddInput(kLengthInput, NodeValue::kRational, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
SetInputProperty(kLengthInput, "min", QVariant::fromValue(rational(0, 1))); SetInputProperty(kLengthInput, QStringLiteral("min"), QVariant::fromValue(rational(0, 1)));
SetInputProperty(kLengthInput, QStringLiteral("view"), RationalSlider::kTime);
SetInputProperty(kLengthInput, QStringLiteral("viewlock"), true);
IgnoreInvalidationsFrom(kLengthInput); IgnoreInvalidationsFrom(kLengthInput);
IgnoreHashingFrom(kLengthInput); IgnoreHashingFrom(kLengthInput);
AddInput(kMediaInInput, NodeValue::kRational, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable)); AddInput(kMediaInInput, NodeValue::kRational, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
SetInputProperty(kMediaInInput, QStringLiteral("view"), RationalSlider::kTime);
SetInputProperty(kMediaInInput, QStringLiteral("viewlock"), true);
IgnoreHashingFrom(kMediaInInput); IgnoreHashingFrom(kMediaInInput);
AddInput(kEnabledInput, NodeValue::kBoolean, true, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable)); AddInput(kEnabledInput, NodeValue::kBoolean, true, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
+15 -20
View File
@@ -160,35 +160,30 @@ void MenuShared::AddItemsForClipEditMenu(Menu *m)
m->addAction(clip_nest_item_); m->addAction(clip_nest_item_);
} }
void MenuShared::AddItemsForTimeRulerMenu(Menu *m, const rational& timebase) void MenuShared::AddItemsForTimeRulerMenu(Menu *m)
{ {
// If a menu is already created (such as the view menu) we need to remove the instance m->addAction(view_timecode_view_dropframe_item_);
// of dropframe or non-dropframe timecode that is already there to avoid double displays m->addAction(view_timecode_view_nondropframe_item_);
if (m->actions().contains(view_timecode_view_dropframe_item_)) {
m->removeAction(view_timecode_view_dropframe_item_);
}
if (m->actions().contains(view_timecode_view_nondropframe_item_)) {
m->removeAction(view_timecode_view_nondropframe_item_);
}
if (Timecode::TimebaseIsDropFrame(timebase)) {
m->addAction(view_timecode_view_dropframe_item_);
m->addAction(view_timecode_view_nondropframe_item_);
} else {
m->addAction(view_timecode_view_nondropframe_item_);
}
m->addAction(view_timecode_view_seconds_item_); m->addAction(view_timecode_view_seconds_item_);
m->addAction(view_timecode_view_frames_item_); m->addAction(view_timecode_view_frames_item_);
m->addAction(view_timecode_view_milliseconds_item_); m->addAction(view_timecode_view_milliseconds_item_);
} }
void MenuShared::AboutToShowTimeRulerActions() void MenuShared::AboutToShowTimeRulerActions(const rational& timebase)
{ {
QList<QAction*> timecode_display_actions = frame_view_mode_group_->actions(); QList<QAction*> timecode_display_actions = frame_view_mode_group_->actions();
Timecode::Display current_timecode_display = Core::instance()->GetTimecodeDisplay();
// Only show the drop-frame option if the timebase is drop-frame
view_timecode_view_dropframe_item_->setVisible(!timebase.isNull() && Timecode::TimebaseIsDropFrame(timebase));
if (!view_timecode_view_dropframe_item_->isVisible() && current_timecode_display == Timecode::kTimecodeDropFrame) {
// If the current setting is drop-frame, correct to non-drop frame
current_timecode_display = Timecode::kTimecodeNonDropFrame;
}
foreach (QAction* a, timecode_display_actions) { foreach (QAction* a, timecode_display_actions) {
if (a->data() == Core::instance()->GetTimecodeDisplay()) { if (a->data() == current_timecode_display) {
a->setChecked(true); a->setChecked(true);
break; break;
} }
+2 -2
View File
@@ -46,9 +46,9 @@ public:
void AddItemsForInOutMenu(Menu* m); void AddItemsForInOutMenu(Menu* m);
void AddColorCodingMenu(Menu* m); void AddColorCodingMenu(Menu* m);
void AddItemsForClipEditMenu(Menu* m); void AddItemsForClipEditMenu(Menu* m);
void AddItemsForTimeRulerMenu(Menu* m, const rational& timebase); void AddItemsForTimeRulerMenu(Menu* m);
void AboutToShowTimeRulerActions(); void AboutToShowTimeRulerActions(const rational& timebase);
static MenuShared* instance(); static MenuShared* instance();
@@ -238,7 +238,7 @@ void NodeParamViewWidgetBridge::SetInputValueInternal(const QVariant &value, int
} }
} }
void NodeParamViewWidgetBridge::ProcessSlider(SliderBase *slider, const QVariant &value) void NodeParamViewWidgetBridge::ProcessSlider(NumericSliderBase *slider, const QVariant &value)
{ {
rational node_time = GetCurrentTimeAsNodeTime(); rational node_time = GetCurrentTimeAsNodeTime();
@@ -406,7 +406,7 @@ void NodeParamViewWidgetBridge::CreateSliders(int count)
{ {
for (int i=0;i<count;i++) { for (int i=0;i<count;i++) {
T* fs = new T(); T* fs = new T();
fs->SetDefaultValue(input_.GetSplitDefaultValueForTrack(i)); fs->SliderBase::SetDefaultValue(input_.GetSplitDefaultValueForTrack(i));
fs->SetLadderElementCount(2); fs->SetLadderElementCount(2);
widgets_.append(fs); widgets_.append(fs);
connect(fs, &T::ValueChanged, this, &NodeParamViewWidgetBridge::WidgetCallback); connect(fs, &T::ValueChanged, this, &NodeParamViewWidgetBridge::WidgetCallback);
@@ -758,6 +758,22 @@ void NodeParamViewWidgetBridge::PropertyChanged(const QString& input, const QStr
} }
} }
if (data_type == NodeValue::kRational) {
if (key == QStringLiteral("view")) {
RationalSlider::DisplayType display_type = static_cast<RationalSlider::DisplayType>(value.toInt());
foreach (QWidget* w, widgets_) {
static_cast<RationalSlider*>(w)->SetDisplayType(display_type);
}
} else if (key == QStringLiteral("viewlock")) {
bool locked = value.toBool();
foreach (QWidget* w, widgets_) {
static_cast<RationalSlider*>(w)->SetLockDisplayType(locked);
}
}
}
// Parameters for files // Parameters for files
if (data_type == NodeValue::kFile) { if (data_type == NodeValue::kFile) {
FileField* ff = static_cast<FileField*>(widgets_.first()); FileField* ff = static_cast<FileField*>(widgets_.first());
@@ -24,7 +24,7 @@
#include <QObject> #include <QObject>
#include "node/inputdragger.h" #include "node/inputdragger.h"
#include "widget/slider/sliderbase.h" #include "widget/slider/base/numericsliderbase.h"
#include "widget/timetarget/timetarget.h" #include "widget/timetarget/timetarget.h"
namespace olive { namespace olive {
@@ -64,7 +64,7 @@ private:
void SetInputValueInternal(const QVariant& value, int track, MultiUndoCommand *command); void SetInputValueInternal(const QVariant& value, int track, MultiUndoCommand *command);
void ProcessSlider(SliderBase* slider, const QVariant& value); void ProcessSlider(NumericSliderBase* slider, const QVariant& value);
template <typename T> template <typename T>
void CreateSliders(int count); void CreateSliders(int count);
+2 -6
View File
@@ -14,6 +14,8 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
add_subdirectory(base)
set(OLIVE_SOURCES set(OLIVE_SOURCES
${OLIVE_SOURCES} ${OLIVE_SOURCES}
widget/slider/floatslider.h widget/slider/floatslider.h
@@ -22,12 +24,6 @@ set(OLIVE_SOURCES
widget/slider/integerslider.cpp widget/slider/integerslider.cpp
widget/slider/rationalslider.h widget/slider/rationalslider.h
widget/slider/rationalslider.cpp widget/slider/rationalslider.cpp
widget/slider/sliderbase.h
widget/slider/sliderbase.cpp
widget/slider/sliderlabel.h
widget/slider/sliderlabel.cpp
widget/slider/sliderladder.h
widget/slider/sliderladder.cpp
widget/slider/stringslider.h widget/slider/stringslider.h
widget/slider/stringslider.cpp widget/slider/stringslider.cpp
widget/slider/timeslider.h widget/slider/timeslider.h
+30
View File
@@ -0,0 +1,30 @@
# 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 <http://www.gnu.org/licenses/>.
set(OLIVE_SOURCES
${OLIVE_SOURCES}
widget/slider/base/decimalsliderbase.h
widget/slider/base/decimalsliderbase.cpp
widget/slider/base/numericsliderbase.h
widget/slider/base/numericsliderbase.cpp
widget/slider/base/sliderbase.h
widget/slider/base/sliderbase.cpp
widget/slider/base/sliderlabel.h
widget/slider/base/sliderlabel.cpp
widget/slider/base/sliderladder.h
widget/slider/base/sliderladder.cpp
PARENT_SCOPE
)
@@ -0,0 +1,63 @@
/***
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 <http://www.gnu.org/licenses/>.
***/
#include "decimalsliderbase.h"
namespace olive {
#define super NumericSliderBase
DecimalSliderBase::DecimalSliderBase(QWidget *parent) :
super(parent),
decimal_places_(2),
autotrim_decimal_places_(false)
{
}
void DecimalSliderBase::SetAutoTrimDecimalPlaces(bool e)
{
autotrim_decimal_places_ = e;
UpdateLabel();
}
QString DecimalSliderBase::FloatToString(double val, int decimal_places, bool autotrim_decimal_places)
{
QString s = QString::number(val, '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;
}
void DecimalSliderBase::SetDecimalPlaces(int i)
{
decimal_places_ = i;
UpdateLabel();
}
}
@@ -0,0 +1,50 @@
/***
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 <http://www.gnu.org/licenses/>.
***/
#ifndef DECIMALSLIDERBASE_H
#define DECIMALSLIDERBASE_H
#include "numericsliderbase.h"
namespace olive {
class DecimalSliderBase : public NumericSliderBase
{
public:
DecimalSliderBase(QWidget* parent = nullptr);
int GetDecimalPlaces() const { return decimal_places_; }
void SetDecimalPlaces(int i);
bool GetAutoTrimDecimalPlaces() const { return autotrim_decimal_places_; };
void SetAutoTrimDecimalPlaces(bool e);
static QString FloatToString(double val, int decimal_places, bool autotrim_decimal_places);
private:
int decimal_places_;
bool autotrim_decimal_places_;
};
}
#endif // DECIMALSLIDERBASE_H
@@ -0,0 +1,203 @@
/***
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 <http://www.gnu.org/licenses/>.
***/
#include "numericsliderbase.h"
#include "common/qtutils.h"
#include "config/config.h"
namespace olive {
NumericSliderBase::NumericSliderBase(QWidget *parent) :
SliderBase(parent),
drag_ladder_(nullptr),
ladder_element_count_(0),
dragged_(false),
has_min_(false),
has_max_(false),
dragged_diff_(0),
drag_multiplier_(1.0),
setting_drag_value_(false)
{
// Numeric sliders are draggable, so we have a cursor that indicates that
setCursor(Qt::SizeHorCursor);
connect(label(), &SliderLabel::LabelPressed, this, &NumericSliderBase::LabelPressed);
}
void NumericSliderBase::SetDragMultiplier(const double &d)
{
drag_multiplier_ = d;
}
void NumericSliderBase::LabelPressed()
{
// Generate width hint
drag_ladder_ = new SliderLadder(drag_multiplier_, ladder_element_count_, GetFormattedValueToString(99999999));
drag_ladder_->SetValue(GetFormattedValueToString());
drag_ladder_->show();
drag_start_value_ = GetValueInternal();
QMetaObject::invokeMethod(this, "RepositionLadder", Qt::QueuedConnection);
connect(drag_ladder_, &SliderLadder::DraggedByValue, this, &NumericSliderBase::LadderDragged);
connect(drag_ladder_, &SliderLadder::Released, this, &NumericSliderBase::LadderReleased);
}
void NumericSliderBase::LadderDragged(int value, double multiplier)
{
dragged_ = true;
dragged_diff_ += value * drag_multiplier_ * multiplier;
// Store current value to try and prevent any unnecessary signalling if the value doesn't change
QVariant pre_set_value = GetValueInternal();
setting_drag_value_ = true;
SetValueInternal(AdjustDragDistanceInternal(drag_start_value_, dragged_diff_));
setting_drag_value_ = false;
if (GetValueInternal() != pre_set_value) {
// We retrieve the value instead of storing it ourselves because SetValueInternal may do extra
// processing (such as clamping).
drag_ladder_->SetValue(GetFormattedValueToString());
if (!UsingLadders()) {
RepositionLadder();
}
ValueSignalEvent(GetValueInternal());
}
}
void NumericSliderBase::LadderReleased()
{
drag_ladder_->deleteLater();
drag_ladder_ = nullptr;
dragged_diff_ = 0;
if (dragged_) {
// This was a drag, send another value changed event
ValueSignalEvent(GetValueInternal());
dragged_ = false;
} else {
ShowEditor();
}
}
void NumericSliderBase::RepositionLadder()
{
if (drag_ladder_) {
if (UsingLadders()) {
drag_ladder_->move(QCursor::pos() - QPoint(drag_ladder_->width()/2, drag_ladder_->height()/2));
} else {
QPoint label_global_pos = label()->mapToGlobal(label()->pos());
int text_width = QtUtils::QFontMetricsWidth(label()->fontMetrics(), label()->text());
if (label()->alignment() & Qt::AlignRight) {
label_global_pos.setX(label_global_pos.x() + label()->width() - text_width);
} else if (label()->alignment() & Qt::AlignHCenter) {
label_global_pos.setX(label_global_pos.x() + label()->width()/2 - text_width/2);
}
int ladder_x = label_global_pos.x() + text_width / 2 - drag_ladder_->width() / 2;
int ladder_y = label_global_pos.y() + label()->height() / 2 - drag_ladder_->height() / 2;
drag_ladder_->move(ladder_x, ladder_y);
}
drag_ladder_->StartListeningToMouseInput();
}
}
bool NumericSliderBase::IsDragging() const
{
return drag_ladder_;
}
bool NumericSliderBase::UsingLadders() const
{
return ladder_element_count_ > 0 && Config::Current()[QStringLiteral("UseSliderLadders")].toBool();
}
QVariant NumericSliderBase::AdjustValue(const QVariant &value) const
{
// Clamps between min/max
if (has_min_ && ValueLessThan(value, min_value_)) {
return min_value_;
} else if (has_max_ && ValueGreaterThan(value, max_value_)) {
return max_value_;
}
return value;
}
void NumericSliderBase::SetOffset(const QVariant &v)
{
offset_ = v;
UpdateLabel();
}
QVariant NumericSliderBase::AdjustDragDistanceInternal(const QVariant &start, const double &drag) const
{
return start.toDouble() + drag;
}
void NumericSliderBase::SetMinimumInternal(const QVariant &v)
{
min_value_ = v;
has_min_ = true;
// Limit value by this new minimum value
if (ValueLessThan(GetValueInternal(), min_value_)) {
SetValueInternal(min_value_);
}
}
void NumericSliderBase::SetMaximumInternal(const QVariant &v)
{
max_value_ = v;
has_max_ = true;
// Limit value by this new maximum value
if (ValueGreaterThan(GetValueInternal(), max_value_)) {
SetValueInternal(max_value_);
}
}
bool NumericSliderBase::ValueGreaterThan(const QVariant &lhs, const QVariant &rhs) const
{
return lhs.toDouble() > rhs.toDouble();
}
bool NumericSliderBase::ValueLessThan(const QVariant &lhs, const QVariant &rhs) const
{
return lhs.toDouble() < rhs.toDouble();
}
bool NumericSliderBase::CanSetValue() const
{
return !IsDragging() || setting_drag_value_;
}
}
+103
View File
@@ -0,0 +1,103 @@
/***
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 <http://www.gnu.org/licenses/>.
***/
#ifndef NUMERICSLIDERBASE_H
#define NUMERICSLIDERBASE_H
#include "sliderbase.h"
namespace olive {
class NumericSliderBase : public SliderBase
{
Q_OBJECT
public:
NumericSliderBase(QWidget *parent = nullptr);
void SetLadderElementCount(int b)
{
ladder_element_count_ = b;
}
void SetDragMultiplier(const double& d);
void SetOffset(const QVariant& v);
bool IsDragging() const;
protected:
const QVariant& GetOffset() const
{
return offset_;
}
virtual QVariant AdjustDragDistanceInternal(const QVariant &start, const double &drag) const;
void SetMinimumInternal(const QVariant& v);
void SetMaximumInternal(const QVariant& v);
virtual bool ValueGreaterThan(const QVariant& lhs, const QVariant& rhs) const;
virtual bool ValueLessThan(const QVariant& lhs, const QVariant& rhs) const;
virtual bool CanSetValue() const override;
private:
bool UsingLadders() const;
virtual QVariant AdjustValue(const QVariant& value) const override;
SliderLadder* drag_ladder_;
int ladder_element_count_;
bool dragged_;
bool has_min_;
QVariant min_value_;
bool has_max_;
QVariant max_value_;
double dragged_diff_;
QVariant drag_start_value_;
QVariant offset_;
double drag_multiplier_;
bool setting_drag_value_;
private slots:
void LabelPressed();
void RepositionLadder();
void LadderDragged(int value, double multiplier);
void LadderReleased();
};
}
#endif // NUMERICSLIDERBASE_H
+230
View File
@@ -0,0 +1,230 @@
/***
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 <http://www.gnu.org/licenses/>.
***/
#include "sliderbase.h"
#include <QDebug>
#include <QEvent>
#include <QMessageBox>
#include "common/qtutils.h"
#include "core.h"
#include "window/mainwindow/mainwindow.h"
namespace olive {
#define super QStackedWidget
SliderBase::SliderBase(QWidget *parent) :
super(parent),
tristate_(false),
format_plural_(false)
{
// Standard (non-numeric) sliders are not draggable, so we indicate as such
setCursor(Qt::PointingHandCursor);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
label_ = new SliderLabel(this);
addWidget(label_);
editor_ = new FocusableLineEdit(this);
addWidget(editor_);
connect(label_, &SliderLabel::focused, this, &SliderBase::ShowEditor);
connect(label_, &SliderLabel::RequestReset, this, &SliderBase::ResetValue);
connect(editor_, &FocusableLineEdit::Confirmed, this, &SliderBase::LineEditConfirmed);
connect(editor_, &FocusableLineEdit::Cancelled, this, &SliderBase::LineEditCancelled);
}
void SliderBase::SetAlignment(Qt::Alignment alignment)
{
label_->setAlignment(alignment);
}
bool SliderBase::IsTristate() const
{
return tristate_;
}
void SliderBase::SetTristate()
{
tristate_ = true;
UpdateLabel();
}
const QVariant &SliderBase::GetValueInternal() const
{
return value_;
}
void SliderBase::SetValueInternal(const QVariant &v)
{
if (!CanSetValue()) {
return;
}
value_ = AdjustValue(v);
// Disable tristate
tristate_ = false;
UpdateLabel();
}
void SliderBase::SetDefaultValue(const QVariant &v)
{
default_value_ = v;
}
void SliderBase::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
UpdateLabel();
}
super::changeEvent(e);
}
void SliderBase::UpdateLabel()
{
label_->setText(tristate_ ? tr("---") : GetFormattedValueToString());
}
QVariant SliderBase::AdjustValue(const QVariant &value) const
{
return value;
}
bool SliderBase::CanSetValue() const
{
return true;
}
void SliderBase::ValueSignalEvent(const QVariant &value)
{
Q_UNUSED(value)
}
void SliderBase::ShowEditor()
{
// This was a simple click
// Load label's text into editor
editor_->setText(ValueToString(value_));
// Show editor
setCurrentWidget(editor_);
// Select all text in the editor
editor_->setFocus();
editor_->selectAll();
}
void SliderBase::LineEditConfirmed()
{
bool is_valid = true;
QVariant test_val = StringToValue(editor_->text(), &is_valid);
// Ensure editor doesn't signal that the focus is lost
editor_->blockSignals(true);
label_->blockSignals(true);
if (is_valid) {
SetValueInternal(test_val);
setCurrentWidget(label_);
ValueSignalEvent(value_);
} else {
QMessageBox::critical(this,
tr("Invalid Value"),
tr("The entered value is not valid for this field."),
QMessageBox::Ok);
// Refocus editor
editor_->setFocus();
}
editor_->blockSignals(false);
label_->blockSignals(false);
}
void SliderBase::LineEditCancelled()
{
// Ensure editor doesn't signal that the focus is lost
editor_->blockSignals(true);
label_->blockSignals(true);
// Set widget back to label
setCurrentWidget(label_);
editor_->blockSignals(false);
label_->blockSignals(false);
}
void SliderBase::ResetValue()
{
if (default_value_.isValid()) {
SetValueInternal(default_value_);
ValueSignalEvent(value_);
}
}
void SliderBase::SetFormat(const QString &s, const bool plural)
{
custom_format_ = s;
format_plural_ = plural;
UpdateLabel();
}
void SliderBase::ClearFormat()
{
custom_format_.clear();
UpdateLabel();
}
bool SliderBase::IsFormatPlural() const
{
return format_plural_;
}
QString SliderBase::GetFormat() const
{
if (custom_format_.isEmpty()) {
return QStringLiteral("%1");
} else {
return custom_format_;
}
}
QString SliderBase::GetFormattedValueToString() const
{
return GetFormattedValueToString(GetValueInternal());
}
QString SliderBase::GetFormattedValueToString(const QVariant &v) const
{
if (format_plural_) {
return tr(GetFormat().toUtf8().constData(), nullptr, v.toInt());
} else {
return GetFormat().arg(ValueToString(v));
}
}
}
@@ -28,84 +28,57 @@
#include "widget/focusablelineedit/focusablelineedit.h" #include "widget/focusablelineedit/focusablelineedit.h"
namespace olive { namespace olive {
class SliderBase : public QStackedWidget class SliderBase : public QStackedWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
enum Mode { SliderBase(QWidget* parent = nullptr);
kString,
kInteger,
kFloat,
kRational
};
SliderBase(Mode mode, QWidget* parent = nullptr);
void SetDragMultiplier(const double& d);
void SetRequireValidInput(bool e);
void SetAlignment(Qt::Alignment alignment); void SetAlignment(Qt::Alignment alignment);
void SetDefaultValue(const QVariant& v);
const QVariant& GetOffset() const
{
return offset_;
}
void SetOffset(const QVariant& v);
bool IsTristate() const; bool IsTristate() const;
void SetTristate(); void SetTristate();
bool IsDragging() const; void SetFormat(const QString& s, const bool plural = false);
void SetFormat(const QString& s, const bool plural=false);
void ClearFormat(); void ClearFormat();
bool IsFormatPlural() const; bool IsFormatPlural() const;
void SetLadderElementCount(int b) void SetDefaultValue(const QVariant& v);
{
ladder_element_count_ = b;
}
signals: QString GetFormattedValueToString(const QVariant& v) const;
void ValueChanged(QVariant v);
public slots:
void ShowEditor();
protected slots:
void UpdateLabel();
protected: protected:
const QVariant& Value() const; const QVariant& GetValueInternal() const;
void SetValue(const QVariant& v); void SetValueInternal(const QVariant& v);
void SetMinimumInternal(const QVariant& v);
void SetMaximumInternal(const QVariant& v);
void UpdateLabel(const QVariant& v);
QLabel* label() { return label_; }
virtual double AdjustDragDistanceInternal(const double& start, const double& drag);
virtual QString ValueToString(const QVariant &v) = 0;
virtual QVariant StringToValue(const QString& s, bool* ok) = 0;
virtual void changeEvent(QEvent* e) override;
void ForceLabelUpdate();
double drag_multiplier_;
private:
const QVariant& ClampValue(const QVariant& v);
QString GetFormat() const; QString GetFormat() const;
bool UsingLadders() const; QString GetFormattedValueToString() const;
SliderLabel* label() { return label_; }
virtual QString ValueToString(const QVariant &v) const = 0;
virtual QVariant StringToValue(const QString& s, bool* ok) const = 0;
virtual QVariant AdjustValue(const QVariant& value) const;
virtual bool CanSetValue() const;
virtual void ValueSignalEvent(const QVariant& value) = 0;
virtual void changeEvent(QEvent* e) override;
private:
SliderLabel* label_; SliderLabel* label_;
FocusableLineEdit* editor_; FocusableLineEdit* editor_;
@@ -113,51 +86,19 @@ private:
QVariant value_; QVariant value_;
QVariant default_value_; QVariant default_value_;
bool has_min_;
QVariant min_value_;
bool has_max_;
QVariant max_value_;
Mode mode_;
double dragged_diff_;
QVariant temp_dragged_value_;
QVariant clamped_temp_dragged_value_;
QVariant offset_;
bool require_valid_input_;
bool tristate_; bool tristate_;
QString custom_format_; QString custom_format_;
bool format_plural_; bool format_plural_;
SliderLadder* drag_ladder_;
int ladder_element_count_;
bool dragged_;
private slots: private slots:
void ShowEditor();
void LabelPressed();
void LadderDragged(int value, double multiplier);
void LadderReleased();
void LineEditConfirmed(); void LineEditConfirmed();
void LineEditCancelled(); void LineEditCancelled();
void ResetValue(); void ResetValue();
void RepositionLadder();
}; };
} }
@@ -63,6 +63,15 @@ void SliderLabel::mousePressEvent(QMouseEvent *e)
} }
} }
void SliderLabel::mouseReleaseEvent(QMouseEvent *e)
{
if (e->button() == Qt::LeftButton) {
if (!(e->modifiers() & Qt::AltModifier)) {
emit LabelReleased();
}
}
}
void SliderLabel::focusInEvent(QFocusEvent *event) void SliderLabel::focusInEvent(QFocusEvent *event)
{ {
QWidget::focusInEvent(event); QWidget::focusInEvent(event);
@@ -34,13 +34,17 @@ public:
SliderLabel(QWidget* parent); SliderLabel(QWidget* parent);
protected: protected:
virtual void mousePressEvent(QMouseEvent *ev) override; virtual void mousePressEvent(QMouseEvent *e) override;
virtual void mouseReleaseEvent(QMouseEvent *e) override;
virtual void focusInEvent(QFocusEvent *event) override; virtual void focusInEvent(QFocusEvent *event) override;
signals: signals:
void LabelPressed(); void LabelPressed();
void LabelReleased();
void focused(); void focused();
void RequestReset(); void RequestReset();
@@ -38,8 +38,7 @@
namespace olive { namespace olive {
SliderLadder::SliderLadder(double drag_multiplier, int nb_outer_values, QString width_hint, QWidget* parent) : SliderLadder::SliderLadder(double drag_multiplier, int nb_outer_values, QString width_hint, QWidget* parent) :
QFrame(parent, Qt::Popup), QFrame(parent, Qt::Popup)
width_hint_(width_hint)
{ {
QVBoxLayout* layout = new QVBoxLayout(this); QVBoxLayout* layout = new QVBoxLayout(this);
layout->setMargin(0); layout->setMargin(0);
@@ -53,17 +52,17 @@ SliderLadder::SliderLadder(double drag_multiplier, int nb_outer_values, QString
} }
for (int i=nb_outer_values-1;i>=0;i--) { for (int i=nb_outer_values-1;i>=0;i--) {
elements_.append(new SliderLadderElement(qPow(10, i + 1) * drag_multiplier, width_hint_)); elements_.append(new SliderLadderElement(qPow(10, i + 1) * drag_multiplier, width_hint));
} }
// Create center entry // Create center entry
SliderLadderElement* start_element = new SliderLadderElement(drag_multiplier, width_hint_); SliderLadderElement* start_element = new SliderLadderElement(drag_multiplier, width_hint);
active_element_ = elements_.size(); active_element_ = elements_.size();
start_element->SetHighlighted(true); start_element->SetHighlighted(true);
elements_.append(start_element); elements_.append(start_element);
for (int i=0;i<nb_outer_values;i++) { for (int i=0;i<nb_outer_values;i++) {
elements_.append(new SliderLadderElement(qPow(10, -i - 1) * drag_multiplier, width_hint_)); elements_.append(new SliderLadderElement(qPow(10, -i - 1) * drag_multiplier, width_hint));
} }
foreach (SliderLadderElement* e, elements_) { foreach (SliderLadderElement* e, elements_) {
@@ -232,7 +231,7 @@ bool SliderLadder::UsingLadders() const
return elements_.size() > 1; return elements_.size() > 1;
} }
SliderLadderElement::SliderLadderElement(const double &multiplier, QString width_hint, QWidget *parent) : SliderLadderElement::SliderLadderElement(const double &multiplier, QString width_hint, QWidget *parent) :
QWidget(parent), QWidget(parent),
multiplier_(multiplier), multiplier_(multiplier),
highlighted_(false), highlighted_(false),
@@ -94,8 +94,6 @@ private:
QTimer drag_timer_; QTimer drag_timer_;
QString width_hint_;
private slots: private slots:
void TimerUpdate(); void TimerUpdate();
+22 -42
View File
@@ -26,25 +26,28 @@
namespace olive { namespace olive {
#define super DecimalSliderBase
FloatSlider::FloatSlider(QWidget *parent) : FloatSlider::FloatSlider(QWidget *parent) :
SliderBase(kFloat, parent), super(parent),
display_type_(kNormal), display_type_(kNormal)
decimal_places_(1),
autotrim_decimal_places_(false)
{ {
SetValue(0.0); SetValue(0.0);
connect(this, SIGNAL(ValueChanged(QVariant)), this, SLOT(ConvertValue(QVariant)));
} }
double FloatSlider::GetValue() double FloatSlider::GetValue() const
{ {
return Value().toDouble(); return GetValueInternal().toDouble();
} }
void FloatSlider::SetValue(const double &d) void FloatSlider::SetValue(const double &d)
{ {
SliderBase::SetValue(d); SetValueInternal(d);
}
void FloatSlider::SetDefaultValue(const double &d)
{
super::SetDefaultValue(d);
} }
void FloatSlider::SetMinimum(const double &d) void FloatSlider::SetMinimum(const double &d)
@@ -57,13 +60,6 @@ void FloatSlider::SetMaximum(const double &d)
SetMaximumInternal(d); SetMaximumInternal(d);
} }
void FloatSlider::SetDecimalPlaces(int i)
{
decimal_places_ = i;
ForceLabelUpdate();
}
void FloatSlider::SetDisplayType(const FloatSlider::DisplayType &type) void FloatSlider::SetDisplayType(const FloatSlider::DisplayType &type)
{ {
display_type_ = type; display_type_ = type;
@@ -81,13 +77,6 @@ void FloatSlider::SetDisplayType(const FloatSlider::DisplayType &type)
} }
} }
void FloatSlider::SetAutoTrimDecimalPlaces(bool e)
{
autotrim_decimal_places_ = e;
ForceLabelUpdate();
}
QString FloatSlider::ValueToString(double val, FloatSlider::DisplayType display, int decimal_places, bool autotrim_decimal_places) QString FloatSlider::ValueToString(double val, FloatSlider::DisplayType display, int decimal_places, bool autotrim_decimal_places)
{ {
switch (display) { switch (display) {
@@ -110,24 +99,15 @@ QString FloatSlider::ValueToString(double val, FloatSlider::DisplayType display,
break; break;
} }
QString s = QString::number(val, 'f', decimal_places); return FloatToString(val, decimal_places, autotrim_decimal_places);
if (autotrim_decimal_places) {
while (s.endsWith('0')
&& s.at(s.size() - 2).isDigit()) {
s = s.left(s.size() - 1);
}
}
return s;
} }
QString FloatSlider::ValueToString(const QVariant &v) QString FloatSlider::ValueToString(const QVariant &v) const
{ {
return ValueToString(v.toDouble() + GetOffset().toDouble(), display_type_, decimal_places_, autotrim_decimal_places_); return ValueToString(v.toDouble() + GetOffset().toDouble(), display_type_, GetDecimalPlaces(), GetAutoTrimDecimalPlaces());
} }
QVariant FloatSlider::StringToValue(const QString &s, bool *ok) QVariant FloatSlider::StringToValue(const QString &s, bool *ok) const
{ {
switch (display_type_) { switch (display_type_) {
case kNormal: case kNormal:
@@ -171,7 +151,7 @@ QVariant FloatSlider::StringToValue(const QString &s, bool *ok)
return s.toDouble(ok) - GetOffset().toDouble(); return s.toDouble(ok) - GetOffset().toDouble();
} }
double FloatSlider::AdjustDragDistanceInternal(const double &start, const double &drag) QVariant FloatSlider::AdjustDragDistanceInternal(const QVariant &start, const double &drag) const
{ {
switch (display_type_) { switch (display_type_) {
case kNormal: case kNormal:
@@ -179,22 +159,22 @@ double FloatSlider::AdjustDragDistanceInternal(const double &start, const double
break; break;
case kDecibel: case kDecibel:
{ {
double current_db = LinearToDecibel(start); double current_db = LinearToDecibel(start.toDouble());
current_db += drag; current_db += drag;
double adjusted_linear = DecibelToLinear(current_db); double adjusted_linear = DecibelToLinear(current_db);
return adjusted_linear; return adjusted_linear;
} }
case kPercentage: case kPercentage:
return SliderBase::AdjustDragDistanceInternal(start, drag * 0.01); return super::AdjustDragDistanceInternal(start, drag * 0.01);
} }
return SliderBase::AdjustDragDistanceInternal(start, drag); return super::AdjustDragDistanceInternal(start, drag);
} }
void FloatSlider::ConvertValue(QVariant v) void FloatSlider::ValueSignalEvent(const QVariant &value)
{ {
emit ValueChanged(v.toDouble()); emit ValueChanged(value.toDouble());
} }
double FloatSlider::LinearToDecibel(double linear) double FloatSlider::LinearToDecibel(double linear)
+10 -17
View File
@@ -21,11 +21,11 @@
#ifndef FLOATSLIDER_H #ifndef FLOATSLIDER_H
#define FLOATSLIDER_H #define FLOATSLIDER_H
#include "sliderbase.h" #include "base/decimalsliderbase.h"
namespace olive { namespace olive {
class FloatSlider : public SliderBase class FloatSlider : public DecimalSliderBase
{ {
Q_OBJECT Q_OBJECT
public: public:
@@ -37,35 +37,32 @@ public:
kPercentage kPercentage
}; };
double GetValue(); double GetValue() const;
void SetValue(const double& d); void SetValue(const double& d);
void SetDefaultValue(const double& d);
void SetMinimum(const double& d); void SetMinimum(const double& d);
void SetMaximum(const double& d); void SetMaximum(const double& d);
void SetDecimalPlaces(int i);
void SetDisplayType(const DisplayType& type); void SetDisplayType(const DisplayType& type);
void SetAutoTrimDecimalPlaces(bool e);
static QString ValueToString(double val, DisplayType display, int decimal_places, bool autotrim_decimal_places); static QString ValueToString(double val, DisplayType display, int decimal_places, bool autotrim_decimal_places);
protected: protected:
virtual QString ValueToString(const QVariant& v) override; virtual QString ValueToString(const QVariant& v) const override;
virtual QVariant StringToValue(const QString& s, bool* ok) override; virtual QVariant StringToValue(const QString& s, bool* ok) const override;
virtual double AdjustDragDistanceInternal(const double& start, const double& drag) override; virtual QVariant AdjustDragDistanceInternal(const QVariant &start, const double &drag) const override;
virtual void ValueSignalEvent(const QVariant &value) override;
signals: signals:
void ValueChanged(double); void ValueChanged(double);
private slots:
void ConvertValue(QVariant v);
private: private:
static double LinearToDecibel(double linear); static double LinearToDecibel(double linear);
@@ -73,10 +70,6 @@ private:
DisplayType display_type_; DisplayType display_type_;
int decimal_places_;
bool autotrim_decimal_places_;
}; };
} }
+19 -9
View File
@@ -22,22 +22,22 @@
namespace olive { namespace olive {
#define super NumericSliderBase
IntegerSlider::IntegerSlider(QWidget* parent) : IntegerSlider::IntegerSlider(QWidget* parent) :
SliderBase(kInteger, parent) super(parent)
{ {
SetValue(0); SetValue(0);
connect(this, SIGNAL(ValueChanged(QVariant)), this, SLOT(ConvertValue(QVariant)));
} }
int64_t IntegerSlider::GetValue() int64_t IntegerSlider::GetValue()
{ {
return Value().toLongLong(); return GetValueInternal().toLongLong();
} }
void IntegerSlider::SetValue(const int64_t &v) void IntegerSlider::SetValue(const int64_t &v)
{ {
SliderBase::SetValue(QVariant::fromValue(v)); SetValueInternal(QVariant::fromValue(v));
} }
void IntegerSlider::SetMinimum(const int64_t &d) void IntegerSlider::SetMinimum(const int64_t &d)
@@ -50,12 +50,17 @@ void IntegerSlider::SetMaximum(const int64_t &d)
SetMaximumInternal(QVariant::fromValue(d)); SetMaximumInternal(QVariant::fromValue(d));
} }
QString IntegerSlider::ValueToString(const QVariant &v) void IntegerSlider::SetDefaultValue(const int64_t &d)
{
super::SetDefaultValue(QVariant::fromValue(d));
}
QString IntegerSlider::ValueToString(const QVariant &v) const
{ {
return QString::number(v.toLongLong() + GetOffset().toLongLong()); return QString::number(v.toLongLong() + GetOffset().toLongLong());
} }
QVariant IntegerSlider::StringToValue(const QString &s, bool *ok) QVariant IntegerSlider::StringToValue(const QString &s, bool *ok) const
{ {
bool valid; bool valid;
@@ -76,9 +81,14 @@ QVariant IntegerSlider::StringToValue(const QString &s, bool *ok)
return QVariant(); return QVariant();
} }
void IntegerSlider::ConvertValue(QVariant v) void IntegerSlider::ValueSignalEvent(const QVariant &value)
{ {
emit ValueChanged(v.toInt()); emit ValueChanged(value.toInt());
}
QVariant IntegerSlider::AdjustDragDistanceInternal(const QVariant &start, const double &drag) const
{
return qRound64(super::AdjustDragDistanceInternal(start, drag).toDouble());
} }
} }
+11 -7
View File
@@ -21,11 +21,11 @@
#ifndef INTEGERSLIDER_H #ifndef INTEGERSLIDER_H
#define INTEGERSLIDER_H #define INTEGERSLIDER_H
#include "sliderbase.h" #include "base/numericsliderbase.h"
namespace olive { namespace olive {
class IntegerSlider : public SliderBase class IntegerSlider : public NumericSliderBase
{ {
Q_OBJECT Q_OBJECT
public: public:
@@ -39,16 +39,20 @@ public:
void SetMaximum(const int64_t& d); void SetMaximum(const int64_t& d);
protected: void SetDefaultValue(const int64_t& d);
virtual QString ValueToString(const QVariant& v) override;
virtual QVariant StringToValue(const QString& s, bool* ok) override; protected:
virtual QString ValueToString(const QVariant& v) const override;
virtual QVariant StringToValue(const QString& s, bool* ok) const override;
virtual void ValueSignalEvent(const QVariant &value) override;
virtual QVariant AdjustDragDistanceInternal(const QVariant &start, const double &drag) const override;
signals: signals:
void ValueChanged(int64_t); void ValueChanged(int64_t);
private slots:
void ConvertValue(QVariant v);
}; };
} }
+104 -86
View File
@@ -1,16 +1,21 @@
/*** /***
Olive - Non-Linear Video Editor Olive - Non-Linear Video Editor
Copyright (C) 2021 Olive Team Copyright (C) 2020 Olive Team
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
***/ ***/
#include "rationalslider.h" #include "rationalslider.h"
@@ -22,40 +27,33 @@
namespace olive { namespace olive {
#define super DecimalSliderBase
RationalSlider::RationalSlider(QWidget *parent) : RationalSlider::RationalSlider(QWidget *parent) :
SliderBase(SliderBase::kRational, parent), super(parent),
display_type_(kTimecode),
decimal_places_(2),
autotrim_decimal_places_(false),
lock_display_type_(false) lock_display_type_(false)
{ {
connect(this, SIGNAL(ValueChanged(QVariant)), this, SLOT(ConvertValue(QVariant))); connect(Core::instance(), &Core::TimecodeDisplayChanged, this, &RationalSlider::UpdateLabel);
connect(Core::instance(), &Core::TimecodeDisplayChanged, this, &RationalSlider::ChangeTimecodeDisplayType); connect(SliderBase::label(), &SliderLabel::customContextMenuRequested, this, &RationalSlider::ShowDisplayTypeMenu);
connect(SliderBase::label(), &SliderLabel::customContextMenuRequested, this, &RationalSlider::changeDisplayType);
SetDisplayType(display_type_); SetDisplayType(kFloat);
SetValue(rational(0, 0)); SetValue(rational(0, 0));
} }
rational RationalSlider::GetValue() rational RationalSlider::GetValue()
{ {
return Value().value<rational>(); return GetValueInternal().value<rational>();
} }
void RationalSlider::SetValue(const rational &d) void RationalSlider::SetValue(const rational &d)
{ {
SliderBase::SetValue(QVariant::fromValue(d)); SetValueInternal(QVariant::fromValue(d));
} }
void RationalSlider::SetDefaultValue(const rational &r) void RationalSlider::SetDefaultValue(const rational &r)
{ {
SliderBase::SetDefaultValue(QVariant::fromValue(r)); super::SetDefaultValue(QVariant::fromValue(r));
}
void RationalSlider::SetDefaultValue(const QVariant &v) {
rational r = v.value<rational>();
SetDefaultValue(r);
} }
void RationalSlider::SetMinimum(const rational &d) void RationalSlider::SetMinimum(const rational &d)
@@ -68,42 +66,19 @@ void RationalSlider::SetMaximum(const rational &d)
SetMaximumInternal(QVariant::fromValue(d)); SetMaximumInternal(QVariant::fromValue(d));
} }
void RationalSlider::SetDecimalPlaces(int i)
{
decimal_places_ = i;
ForceLabelUpdate();
}
void RationalSlider::SetTimebase(const rational &timebase) void RationalSlider::SetTimebase(const rational &timebase)
{ {
timebase_ = timebase; timebase_ = timebase;
// Refresh label since we have a new timebase to generate a timecode with // Refresh label since we have a new timebase to generate a timecode with
UpdateLabel(Value()); UpdateLabel();
}
void RationalSlider::SetAutoTrimDecimalPlaces(bool e) {
autotrim_decimal_places_ = e;
ForceLabelUpdate();
} }
void RationalSlider::SetDisplayType(const RationalSlider::DisplayType &type) void RationalSlider::SetDisplayType(const RationalSlider::DisplayType &type)
{ {
display_type_ = type; display_type_ = type;
switch (display_type_) { UpdateLabel();
case kTimecode:
ClearFormat();
break;
case kTimestamp:
SetFormat("%1 Frames");
break;
case kFloat:
SetFormat("%1 s");
break;
}
} }
void RationalSlider::SetLockDisplayType(bool e) void RationalSlider::SetLockDisplayType(bool e)
@@ -111,87 +86,130 @@ void RationalSlider::SetLockDisplayType(bool e)
lock_display_type_ = e; lock_display_type_ = e;
} }
bool RationalSlider::LockDisplayType() bool RationalSlider::GetLockDisplayType()
{ {
return lock_display_type_; return lock_display_type_;
} }
QString RationalSlider::ValueToString(const QVariant &v) void RationalSlider::DisableDisplayType(RationalSlider::DisplayType type)
{ {
double time = v.value<rational>().toDouble() + GetOffset().value<rational>().toDouble(); disabled_.append(type);
}
QString RationalSlider::ValueToString(const QVariant &v) const
{
double val = v.value<rational>().toDouble() + GetOffset().value<rational>().toDouble();
switch (display_type_) { switch (display_type_) {
case kTimecode: case kTime:
return Timecode::time_to_timecode(v.value<rational>(), timebase_, Core::instance()->GetTimecodeDisplay()); return Timecode::time_to_timecode(v.value<rational>(), timebase_, Core::instance()->GetTimecodeDisplay());
case kTimestamp: case kFloat:
return QString::number(Timecode::time_to_timestamp(time, timebase_)); return FloatToString(val, GetDecimalPlaces(), GetAutoTrimDecimalPlaces());
case kFloat: case kRational:
{ return v.value<rational>().toString();
QString s = QString::number(time, '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 v.toString(); return v.toString();
} }
QVariant RationalSlider::StringToValue(const QString &s, bool *ok) QVariant RationalSlider::StringToValue(const QString &s, bool *ok) const
{ {
rational r; rational r;
*ok = false; *ok = false;
switch (display_type_) { switch (display_type_) {
case kTimecode: case kTime:
{ {
int t = Timecode::timecode_to_timestamp(s, timebase_, Core::instance()->GetTimecodeDisplay(), ok); r = Timecode::timecode_to_time(s, timebase_, Core::instance()->GetTimecodeDisplay(), ok);
r = rational(t, timebase_.denominator()); break;
}
case kFloat:
{
// First, convert to a double
double d = s.toDouble(ok);
if (!(*ok)) {
break; break;
} }
case kTimestamp:
r = rational(s.toInt(ok), timebase_.denominator()); // If double conversion succeeded, convert to a rational
break; r = rational::fromDouble(d, ok);
case kFloat: break;
r = rational::fromDouble(s.toDouble(ok)); }
if (!r.isNull()) { case kRational:
*ok = true; r = rational::fromString(s, ok);
} break;
break;
} }
return QVariant::fromValue(r - GetOffset().value<rational>()); //return QVariant::fromValue(r - GetOffset().value<rational>());
return QVariant::fromValue(r);
} }
double RationalSlider::AdjustDragDistanceInternal(const double &start, const double &drag) QVariant RationalSlider::AdjustDragDistanceInternal(const QVariant &start, const double &drag) const
{ {
// Assume we want smallest increment to be timebase or 1 frame // Assume we want smallest increment to be timebase or 1 frame
return start + drag*timebase_.toDouble(); return QVariant::fromValue(start.value<rational>() + rational::fromDouble(drag)*timebase_);
} }
void RationalSlider::ConvertValue(QVariant v) void RationalSlider::ValueSignalEvent(const QVariant &v)
{ {
emit ValueChanged(v.value<rational>()); emit ValueChanged(v.value<rational>());
} }
void RationalSlider::changeDisplayType() bool RationalSlider::ValueGreaterThan(const QVariant &lhs, const QVariant &rhs) const
{ {
if (!LockDisplayType()) { return lhs.value<rational>() > rhs.value<rational>();
Menu m(this); }
MenuShared::instance()->AddItemsForTimeRulerMenu(&m, timebase_);
MenuShared::instance()->AboutToShowTimeRulerActions();
bool RationalSlider::ValueLessThan(const QVariant &lhs, const QVariant &rhs) const
{
return lhs.value<rational>() < rhs.value<rational>();
}
void RationalSlider::ShowDisplayTypeMenu()
{
Menu m(this);
if (!GetLockDisplayType()) {
if (!disabled_.contains(kFloat)) {
QAction* float_action = m.addAction(tr("Float"));
float_action->setData(kFloat);
connect(float_action, &QAction::triggered, this, &RationalSlider::SetDisplayTypeFromMenu);
}
if (!disabled_.contains(kRational)) {
QAction* rational_action = m.addAction(tr("Rational"));
rational_action->setData(kRational);
connect(rational_action, &QAction::triggered, this, &RationalSlider::SetDisplayTypeFromMenu);
}
if (!disabled_.contains(kTime)) {
QAction* time_action = m.addAction(tr("Time"));
time_action->setData(kTime);
connect(time_action, &QAction::triggered, this, &RationalSlider::SetDisplayTypeFromMenu);
}
}
if (display_type_ == kTime) {
if (!m.actions().isEmpty()) {
m.addSeparator();
}
MenuShared::instance()->AddItemsForTimeRulerMenu(&m);
MenuShared::instance()->AboutToShowTimeRulerActions(timebase_);
}
if (!m.actions().isEmpty()) {
m.exec(QCursor::pos()); m.exec(QCursor::pos());
ForceLabelUpdate(); UpdateLabel();
} }
} }
void RationalSlider::ChangeTimecodeDisplayType() void RationalSlider::SetDisplayTypeFromMenu()
{ {
ForceLabelUpdate(); QAction* action = static_cast<QAction*>(sender());
DisplayType type = static_cast<DisplayType>(action->data().toInt());
SetDisplayType(type);
} }
} }
+32 -35
View File
@@ -1,36 +1,40 @@
/*** /***
Olive - Non-Linear Video Editor Olive - Non-Linear Video Editor
Copyright (C) 2021 Olive Team Copyright (C) 2020 Olive Team
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
***/ ***/
#ifndef RATIONALSLIDER_H #ifndef RATIONALSLIDER_H
#define RATIONALSLIDER_H #define RATIONALSLIDER_H
#include "sliderbase.h"
#include <QMouseEvent> #include <QMouseEvent>
#include "base/decimalsliderbase.h"
#include "common/rational.h" #include "common/rational.h"
namespace olive { namespace olive {
/** /**
* @brief A olive::rational based slider * @brief A olive::rational based slider
* *
* A slider that can display rationals as either timecode (drop or non-drop), a timestamp (frames), * A slider that can display rationals as either timecode (drop or non-drop), a timestamp (frames),
* or a float (seconds). * or a float (seconds).
*/ */
class RationalSlider : public SliderBase class RationalSlider : public DecimalSliderBase
{ {
Q_OBJECT Q_OBJECT
public: public:
@@ -38,9 +42,9 @@ public:
* @brief enum containing the possibly display types * @brief enum containing the possibly display types
*/ */
enum DisplayType { enum DisplayType {
kTimecode, kTime,
kTimestamp, kFloat,
kFloat kRational
}; };
RationalSlider(QWidget* parent = nullptr); RationalSlider(QWidget* parent = nullptr);
@@ -60,11 +64,6 @@ public:
*/ */
void SetDefaultValue(const rational& r); void SetDefaultValue(const rational& r);
/**
* @brief Sets the sliders default value
*/
void SetDefaultValue(const QVariant& v);
/** /**
* @brief Sets the sliders minimum value * @brief Sets the sliders minimum value
*/ */
@@ -75,11 +74,6 @@ public:
*/ */
void SetMaximum(const rational& d); 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 * @brief Sets the sliders timebase which is also the minimum increment of the slider
*/ */
@@ -98,40 +92,43 @@ public:
/** /**
* @brief Get whether the user can change the display type or not * @brief Get whether the user can change the display type or not
*/ */
bool LockDisplayType(); bool GetLockDisplayType();
void SetAutoTrimDecimalPlaces(bool e); /**
* @brief Hide display type in menu
*/
void DisableDisplayType(DisplayType type);
protected: protected:
virtual QString ValueToString(const QVariant& v) override; virtual QString ValueToString(const QVariant& v) const override;
virtual QVariant StringToValue(const QString& s, bool* ok) override; virtual QVariant StringToValue(const QString& s, bool* ok) const override;
virtual double AdjustDragDistanceInternal(const double& start, const double& drag) override; virtual QVariant AdjustDragDistanceInternal(const QVariant &start, const double &drag) const override;
virtual void ValueSignalEvent(const QVariant& v) override;
virtual bool ValueGreaterThan(const QVariant& lhs, const QVariant& rhs) const override;
virtual bool ValueLessThan(const QVariant& lhs, const QVariant& rhs) const override;
signals: signals:
void ValueChanged(rational); void ValueChanged(rational);
private slots: private slots:
void ConvertValue(QVariant v); void ShowDisplayTypeMenu();
void changeDisplayType(); void SetDisplayTypeFromMenu();
/**
* @brief Changes the timecodes display type (e.g. drop frome to none drop frame)
*/
void ChangeTimecodeDisplayType();
private: private:
DisplayType display_type_; DisplayType display_type_;
int decimal_places_;
bool autotrim_decimal_places_;
rational timebase_; rational timebase_;
bool lock_display_type_; bool lock_display_type_;
QVector<DisplayType> disabled_;
}; };
} }
-470
View File
@@ -1,470 +0,0 @@
/***
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 <http://www.gnu.org/licenses/>.
***/
#include "sliderbase.h"
#include <QDebug>
#include <QEvent>
#include <QMessageBox>
#include "common/qtutils.h"
#include "core.h"
#include "window/mainwindow/mainwindow.h"
namespace olive {
SliderBase::SliderBase(Mode mode, QWidget *parent) :
QStackedWidget(parent),
drag_multiplier_(1.0),
has_min_(false),
has_max_(false),
mode_(mode),
dragged_diff_(0),
require_valid_input_(true),
tristate_(false),
format_plural_(false),
drag_ladder_(nullptr),
ladder_element_count_(0),
dragged_(false)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
label_ = new SliderLabel(this);
addWidget(label_);
editor_ = new FocusableLineEdit(this);
addWidget(editor_);
connect(label_, &SliderLabel::LabelPressed, this, &SliderBase::LabelPressed);
connect(label_, &SliderLabel::focused, this, &SliderBase::ShowEditor);
connect(label_, &SliderLabel::RequestReset, this, &SliderBase::ResetValue);
connect(editor_, &FocusableLineEdit::Confirmed, this, &SliderBase::LineEditConfirmed);
connect(editor_, &FocusableLineEdit::Cancelled, this, &SliderBase::LineEditCancelled);
// Set valid cursor based on mode
switch (mode_) {
case kString:
setCursor(Qt::PointingHandCursor);
break;
case kInteger:
case kFloat:
case kRational:
setCursor(Qt::SizeHorCursor);
break;
}
}
void SliderBase::SetDragMultiplier(const double &d)
{
drag_multiplier_ = d;
}
void SliderBase::SetRequireValidInput(bool e)
{
require_valid_input_ = e;
}
void SliderBase::SetAlignment(Qt::Alignment alignment)
{
label_->setAlignment(alignment);
}
bool SliderBase::IsTristate() const
{
return tristate_;
}
void SliderBase::SetTristate()
{
tristate_ = true;
UpdateLabel(0);
}
bool SliderBase::IsDragging() const
{
return drag_ladder_;
}
void SliderBase::SetFormat(const QString &s, const bool plural)
{
custom_format_ = s;
format_plural_ = plural;
ForceLabelUpdate();
}
void SliderBase::ClearFormat()
{
custom_format_.clear();
ForceLabelUpdate();
}
bool SliderBase::IsFormatPlural() const
{
return format_plural_;
}
void SliderBase::ForceLabelUpdate()
{
UpdateLabel(Value());
}
const QVariant &SliderBase::Value() const
{
if (IsDragging()) {
return clamped_temp_dragged_value_;
}
return value_;
}
void SliderBase::SetValue(const QVariant &v)
{
if (IsDragging()) {
return;
}
value_ = ClampValue(v);
// Disable tristate
tristate_ = false;
UpdateLabel(value_);
}
void SliderBase::SetDefaultValue(const QVariant &v)
{
default_value_ = v;
}
void SliderBase::SetOffset(const QVariant &v)
{
offset_ = v;
UpdateLabel(value_);
}
void SliderBase::SetMinimumInternal(const QVariant &v)
{
min_value_ = v;
has_min_ = true;
// Limit value by this new minimum value
if (mode_ == kRational) {
if (value_.value<rational>().toDouble() < min_value_.value<rational>().toDouble()) {
SetValue(min_value_);
}
} else {
if (value_.toDouble() < min_value_.toDouble()) {
SetValue(min_value_);
}
}
}
void SliderBase::SetMaximumInternal(const QVariant &v)
{
max_value_ = v;
has_max_ = true;
// Limit value by this new maximum value
if (mode_ == kRational) {
if (value_.value<rational>().toDouble() > max_value_.value<rational>().toDouble()) {
SetValue(max_value_);
}
} else {
if (value_.toDouble() > max_value_.toDouble()) {
SetValue(max_value_);
}
}
}
void SliderBase::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
UpdateLabel(value_);
}
QStackedWidget::changeEvent(e);
}
const QVariant &SliderBase::ClampValue(const QVariant &v)
{
double value, min, max;
if (mode_ == kRational) {
value = v.value<rational>().toDouble();
min = min_value_.value<rational>().toDouble();
max = max_value_.value<rational>().toDouble();
} else {
value = v.toDouble();
min = min_value_.toDouble();
max = max_value_.toDouble();
}
if (has_min_ && value < min) {
return min_value_;
}else if (has_max_ && value > max) {
return max_value_;
}
return v;
}
QString SliderBase::GetFormat() const
{
if (custom_format_.isEmpty()) {
return QStringLiteral("%1");
} else {
return custom_format_;
}
}
bool SliderBase::UsingLadders() const
{
return ladder_element_count_ > 0 && Config::Current()[QStringLiteral("UseSliderLadders")].toBool();
}
void SliderBase::UpdateLabel(const QVariant &v)
{
if (tristate_) {
label_->setText("---");
} else if (format_plural_) {
label_->setText(tr(GetFormat().toUtf8().constData(), nullptr, v.toInt()));
} else {
label_->setText(GetFormat().arg(ValueToString(v)));
}
}
double SliderBase::AdjustDragDistanceInternal(const double &start, const double &drag)
{
return start + drag;
}
QString SliderBase::ValueToString(const QVariant &v)
{
return v.toString();
}
QVariant SliderBase::StringToValue(const QString &s, bool *ok)
{
*ok = true;
return s;
}
void SliderBase::ShowEditor()
{
// This was a simple click
// Load label's text into editor
editor_->setText(ValueToString(value_));
// Show editor
setCurrentWidget(editor_);
// Select all text in the editor
editor_->setFocus();
editor_->selectAll();
}
void SliderBase::LabelPressed()
{
switch (mode_) {
case kString:
// No dragging supported for strings
break;
case kInteger:
case kFloat:
case kRational:
{
if (mode_ == kRational) {
drag_ladder_ = new SliderLadder(drag_multiplier_, ladder_element_count_, "00:00:00:00");
} else {
drag_ladder_ = new SliderLadder(drag_multiplier_, ladder_element_count_, "00000000");
}
drag_ladder_->SetValue(ValueToString(value_));
drag_ladder_->show();
QMetaObject::invokeMethod(this, "RepositionLadder", Qt::QueuedConnection);
connect(drag_ladder_, &SliderLadder::DraggedByValue, this, &SliderBase::LadderDragged);
connect(drag_ladder_, &SliderLadder::Released, this, &SliderBase::LadderReleased);
break;
}
}
}
void SliderBase::LadderDragged(int value, double multiplier)
{
dragged_ = true;
switch (mode_) {
case kString:
// No dragging supported for strings
break;
case kInteger:
case kFloat:
{
dragged_diff_ += value * drag_multiplier_ * multiplier;
double drag_val = AdjustDragDistanceInternal(value_.toDouble(), dragged_diff_);
// Update temporary value
if (mode_ == kInteger) {
temp_dragged_value_ = qRound(drag_val);
} else {
temp_dragged_value_ = drag_val;
}
clamped_temp_dragged_value_ = ClampValue(temp_dragged_value_);
UpdateLabel(clamped_temp_dragged_value_);
drag_ladder_->SetValue(ValueToString(clamped_temp_dragged_value_));
if (!UsingLadders()) {
RepositionLadder();
}
emit ValueChanged(clamped_temp_dragged_value_);
break;
}
case kRational:
{
dragged_diff_ += value * drag_multiplier_ * multiplier;
double drag_val = AdjustDragDistanceInternal(value_.value<rational>().toDouble(), dragged_diff_);
rational d_v;
d_v = rational::fromDouble(drag_val);
temp_dragged_value_.setValue(d_v);
clamped_temp_dragged_value_ = ClampValue(temp_dragged_value_);
UpdateLabel(temp_dragged_value_);
drag_ladder_->SetValue(ValueToString(clamped_temp_dragged_value_));
if (!Config::Current()[QStringLiteral("UseSliderLadders")].toBool()) {
RepositionLadder();
}
emit ValueChanged(clamped_temp_dragged_value_);
break;
}
}
}
void SliderBase::LadderReleased()
{
drag_ladder_->deleteLater();
drag_ladder_ = nullptr;
dragged_diff_ = 0;
if (dragged_) {
// This was a drag
switch (mode_) {
case kString:
// No-op
break;
case kInteger:
SetValue(clamped_temp_dragged_value_.toInt());
break;
case kFloat:
SetValue(clamped_temp_dragged_value_.toDouble());
break;
case kRational:
SetValue(temp_dragged_value_);
}
emit ValueChanged(value_);
dragged_ = false;
} else {
ShowEditor();
}
}
void SliderBase::LineEditConfirmed()
{
bool is_valid = true;
QVariant test_val = StringToValue(editor_->text(), &is_valid);
// Ensure editor doesn't signal that the focus is lost
editor_->blockSignals(true);
label_->blockSignals(true);
if (is_valid) {
SetValue(test_val);
setCurrentWidget(label_);
emit ValueChanged(value_);
} else if (require_valid_input_ && !IsTristate()) {
QMessageBox::critical(this,
tr("Invalid Value"),
tr("The entered value is not valid for this field."),
QMessageBox::Ok);
// Refocus editor
editor_->setFocus();
}
editor_->blockSignals(false);
label_->blockSignals(false);
}
void SliderBase::LineEditCancelled()
{
// Ensure editor doesn't signal that the focus is lost
editor_->blockSignals(true);
label_->blockSignals(true);
// Set widget back to label
setCurrentWidget(label_);
editor_->blockSignals(false);
label_->blockSignals(false);
}
void SliderBase::ResetValue()
{
if (!default_value_.isNull()) {
SetValue(default_value_);
emit ValueChanged(value_);
}
}
void SliderBase::RepositionLadder()
{
if (drag_ladder_) {
if (UsingLadders()) {
drag_ladder_->move(QCursor::pos() - QPoint(drag_ladder_->width()/2, drag_ladder_->height()/2));
} else {
QPoint label_global_pos = label_->mapToGlobal(label_->pos());
int text_width = QtUtils::QFontMetricsWidth(label_->fontMetrics(), label_->text());
int ladder_x = label_global_pos.x() + text_width / 2 - drag_ladder_->width() / 2;
int ladder_y = label_global_pos.y() + label_->height() / 2 - drag_ladder_->height() / 2;
drag_ladder_->move(ladder_x, ladder_y);
}
drag_ladder_->StartListeningToMouseInput();
}
}
}
+21 -8
View File
@@ -22,33 +22,46 @@
namespace olive { namespace olive {
#define super SliderBase
StringSlider::StringSlider(QWidget* parent) : StringSlider::StringSlider(QWidget* parent) :
SliderBase(kString, parent) super(parent)
{ {
SetValue(QString()); SetValue(QString());
connect(this, SIGNAL(ValueChanged(QVariant)), this, SLOT(ConvertValue(QVariant))); connect(label(), &SliderLabel::LabelReleased, this, &SliderBase::ShowEditor);
} }
QString StringSlider::GetValue() QString StringSlider::GetValue() const
{ {
return Value().toString(); return GetValueInternal().toString();
} }
void StringSlider::SetValue(const QString &v) void StringSlider::SetValue(const QString &v)
{ {
SliderBase::SetValue(v); SetValueInternal(v);
} }
QString StringSlider::ValueToString(const QVariant &v) void StringSlider::SetDefaultValue(const QString &v)
{
super::SetDefaultValue(v);
}
QString StringSlider::ValueToString(const QVariant &v) const
{ {
QString vstr = v.toString(); QString vstr = v.toString();
return (vstr.isEmpty()) ? tr("(none)") : vstr; return (vstr.isEmpty()) ? tr("(none)") : vstr;
} }
void StringSlider::ConvertValue(QVariant v) QVariant StringSlider::StringToValue(const QString &s, bool *ok) const
{ {
emit ValueChanged(v.toString()); *ok = true;
return s;
}
void StringSlider::ValueSignalEvent(const QVariant &value)
{
emit ValueChanged(value.toString());
} }
} }
+11 -7
View File
@@ -21,7 +21,7 @@
#ifndef STRINGSLIDER_H #ifndef STRINGSLIDER_H
#define STRINGSLIDER_H #define STRINGSLIDER_H
#include "sliderbase.h" #include "base/sliderbase.h"
namespace olive { namespace olive {
@@ -33,18 +33,22 @@ public:
void SetDragMultiplier(const double& d) = delete; void SetDragMultiplier(const double& d) = delete;
QString GetValue(); QString GetValue() const;
void SetValue(const QString& v); void SetValue(const QString& v);
protected: void SetDefaultValue(const QString& v);
virtual QString ValueToString(const QVariant& value) override;
signals: signals:
void ValueChanged(QString); void ValueChanged(const QString& str);
protected:
virtual QString ValueToString(const QVariant& value) const override;
virtual QVariant StringToValue(const QString &s, bool *ok) const override;
virtual void ValueSignalEvent(const QVariant &value) override;
private slots:
void ConvertValue(QVariant v);
}; };
} }
+8 -12
View File
@@ -25,13 +25,14 @@
namespace olive { namespace olive {
#define super IntegerSlider
TimeSlider::TimeSlider(QWidget *parent) : TimeSlider::TimeSlider(QWidget *parent) :
IntegerSlider(parent) super(parent)
{ {
SetMinimum(0); SetMinimum(0);
SetValue(0);
connect(Core::instance(), &Core::TimecodeDisplayChanged, this, &TimeSlider::TimecodeDisplayChanged); connect(Core::instance(), &Core::TimecodeDisplayChanged, this, &TimeSlider::UpdateLabel);
} }
void TimeSlider::SetTimebase(const rational &timebase) void TimeSlider::SetTimebase(const rational &timebase)
@@ -39,14 +40,14 @@ void TimeSlider::SetTimebase(const rational &timebase)
timebase_ = timebase; timebase_ = timebase;
// Refresh label since we have a new timebase to generate a timecode with // Refresh label since we have a new timebase to generate a timecode with
UpdateLabel(Value()); UpdateLabel();
} }
QString TimeSlider::ValueToString(const QVariant &v) QString TimeSlider::ValueToString(const QVariant &v) const
{ {
if (timebase_.isNull()) { if (timebase_.isNull()) {
// We can't generate a timecode without a timebase, so we just return the number // We can't generate a timecode without a timebase, so we just return the number
return IntegerSlider::ValueToString(v); return super::ValueToString(v);
} }
return Timecode::timestamp_to_timecode(v.toLongLong() + GetOffset().toLongLong(), return Timecode::timestamp_to_timecode(v.toLongLong() + GetOffset().toLongLong(),
@@ -54,14 +55,9 @@ QString TimeSlider::ValueToString(const QVariant &v)
Core::instance()->GetTimecodeDisplay()); Core::instance()->GetTimecodeDisplay());
} }
QVariant TimeSlider::StringToValue(const QString &s, bool *ok) QVariant TimeSlider::StringToValue(const QString &s, bool *ok) const
{ {
return QVariant::fromValue(Timecode::timecode_to_timestamp(s, timebase_, Core::instance()->GetTimecodeDisplay(), ok) - GetOffset().toLongLong()); return QVariant::fromValue(Timecode::timecode_to_timestamp(s, timebase_, Core::instance()->GetTimecodeDisplay(), ok) - GetOffset().toLongLong());
} }
void TimeSlider::TimecodeDisplayChanged()
{
UpdateLabel(Value());
}
} }
+2 -5
View File
@@ -35,16 +35,13 @@ public:
void SetTimebase(const rational& timebase); void SetTimebase(const rational& timebase);
protected: protected:
virtual QString ValueToString(const QVariant& v) override; virtual QString ValueToString(const QVariant& v) const override;
virtual QVariant StringToValue(const QString& s, bool* ok) override; virtual QVariant StringToValue(const QString& s, bool* ok) const override;
private: private:
rational timebase_; rational timebase_;
private slots:
void TimecodeDisplayChanged();
}; };
} }
+2 -2
View File
@@ -306,8 +306,8 @@ void TimeRuler::ShowContextMenu()
{ {
Menu m(this); Menu m(this);
MenuShared::instance()->AddItemsForTimeRulerMenu(&m, timebase()); MenuShared::instance()->AddItemsForTimeRulerMenu(&m);
MenuShared::instance()->AboutToShowTimeRulerActions(); MenuShared::instance()->AboutToShowTimeRulerActions(timebase());
m.exec(QCursor::pos()); m.exec(QCursor::pos());
} }
+8 -6
View File
@@ -97,11 +97,13 @@ VideoParamEdit::VideoParamEdit(QWidget* parent) :
connect(frame_rate_combobox_, static_cast<void (FrameRateComboBox::*)(int)>(&FrameRateComboBox::currentIndexChanged), this, &VideoParamEdit::Changed); connect(frame_rate_combobox_, static_cast<void (FrameRateComboBox::*)(int)>(&FrameRateComboBox::currentIndexChanged), this, &VideoParamEdit::Changed);
layout->addWidget(frame_rate_combobox_, row, 1); layout->addWidget(frame_rate_combobox_, row, 1);
// FIXME: Replace with rational slider frame_rate_slider_ = new RationalSlider();
frame_rate_slider_ = new FloatSlider();
frame_rate_slider_->SetMinimum(0); frame_rate_slider_->SetMinimum(0);
frame_rate_slider_->SetDecimalPlaces(2); frame_rate_slider_->SetDecimalPlaces(3);
connect(frame_rate_slider_, &FloatSlider::ValueChanged, this, &VideoParamEdit::Changed); frame_rate_slider_->SetAutoTrimDecimalPlaces(true);
frame_rate_slider_->SetTimebase(rational(1, 1000)); // Drag interval
frame_rate_slider_->DisableDisplayType(RationalSlider::kTime);
connect(frame_rate_slider_, &RationalSlider::ValueChanged, this, &VideoParamEdit::Changed);
layout->addWidget(frame_rate_slider_, row, 1); layout->addWidget(frame_rate_slider_, row, 1);
row++; row++;
@@ -277,7 +279,7 @@ VideoParams VideoParamEdit::GetVideoParams() const
rational using_frame_rate; rational using_frame_rate;
if (mask_ & kFrameRateIsArbitrary) { if (mask_ & kFrameRateIsArbitrary) {
using_frame_rate = rational::fromDouble(frame_rate_slider_->GetValue()); using_frame_rate = frame_rate_slider_->GetValue();
} else { } else {
using_frame_rate = frame_rate_combobox_->GetFrameRate(); using_frame_rate = frame_rate_combobox_->GetFrameRate();
} }
@@ -316,7 +318,7 @@ void VideoParamEdit::SetVideoParams(const VideoParams &p)
depth_slider_->SetValue(p.depth()); depth_slider_->SetValue(p.depth());
frame_rate_combobox_->SetFrameRate(p.frame_rate()); frame_rate_combobox_->SetFrameRate(p.frame_rate());
frame_rate_slider_->SetValue(p.frame_rate().toDouble()); frame_rate_slider_->SetValue(p.frame_rate());
timebase_temp_ = p.time_base(); timebase_temp_ = p.time_base();
pixel_aspect_combobox_->SetPixelAspectRatio(p.pixel_aspect_ratio()); pixel_aspect_combobox_->SetPixelAspectRatio(p.pixel_aspect_ratio());
+2 -2
View File
@@ -27,8 +27,8 @@
#include "node/color/colormanager/colormanager.h" #include "node/color/colormanager/colormanager.h"
#include "render/videoparams.h" #include "render/videoparams.h"
#include "widget/slider/floatslider.h"
#include "widget/slider/integerslider.h" #include "widget/slider/integerslider.h"
#include "widget/slider/rationalslider.h"
#include "widget/standardcombos/frameratecombobox.h" #include "widget/standardcombos/frameratecombobox.h"
#include "widget/standardcombos/interlacedcombobox.h" #include "widget/standardcombos/interlacedcombobox.h"
#include "widget/standardcombos/pixelaspectratiocombobox.h" #include "widget/standardcombos/pixelaspectratiocombobox.h"
@@ -145,7 +145,7 @@ private:
IntegerSlider* depth_slider_; IntegerSlider* depth_slider_;
QLabel* frame_rate_lbl_; QLabel* frame_rate_lbl_;
FrameRateComboBox* frame_rate_combobox_; FrameRateComboBox* frame_rate_combobox_;
FloatSlider* frame_rate_slider_; RationalSlider* frame_rate_slider_;
QLabel* pixel_aspect_lbl_; QLabel* pixel_aspect_lbl_;
PixelAspectRatioComboBox* pixel_aspect_combobox_; PixelAspectRatioComboBox* pixel_aspect_combobox_;
QLabel* interlaced_lbl_; QLabel* interlaced_lbl_;
+2 -2
View File
@@ -308,12 +308,12 @@ void MainMenu::ViewMenuAboutToShow()
if (p) { if (p) {
if (p->timebase().denominator() != 0) { if (p->timebase().denominator() != 0) {
view_menu_->addSeparator(); view_menu_->addSeparator();
MenuShared::instance()->AddItemsForTimeRulerMenu(view_menu_, p->timebase()); MenuShared::instance()->AddItemsForTimeRulerMenu(view_menu_);
} }
} }
// Ensure checked timecode display mode is correct // Ensure checked timecode display mode is correct
MenuShared::instance()->AboutToShowTimeRulerActions(); MenuShared::instance()->AboutToShowTimeRulerActions(p->timebase());
} }
void MainMenu::ToolsMenuAboutToShow() void MainMenu::ToolsMenuAboutToShow()