slider: reworked sliderbase and derivatives
Mostly cleaning up code, SliderBase was fairly messy.
This commit is contained in:
+26
-7
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ public:
|
|||||||
static QString timestamp_to_timecode(const int64_t ×tamp, const rational& timebase, const Display &display, bool show_plus_if_positive = false);
|
static QString timestamp_to_timecode(const int64_t ×tamp, 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_;
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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_;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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();
|
||||||
|
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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_;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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_;
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user