implemented color picker in dialog

Fixes #1757
This commit is contained in:
itsmattkc
2021-10-01 15:41:24 -07:00
parent ee81a47f2e
commit 7b65ecace5
13 changed files with 328 additions and 28 deletions
+1
View File
@@ -98,6 +98,7 @@ void Config::SetDefaults()
SetEntryInternal(QStringLiteral("ShowWelcomeDialog"), NodeValue::kBoolean, true);
SetEntryInternal(QStringLiteral("ShowClipWhileDragging"), NodeValue::kBoolean, true);
SetEntryInternal(QStringLiteral("StopPlaybackOnLastFrame"), NodeValue::kBoolean, false);
SetEntryInternal(QStringLiteral("UseLegacyColorInInputTab"), NodeValue::kBoolean, false);
SetEntryInternal(QStringLiteral("AutoCacheDelay"), NodeValue::kInt, 1000);
+21 -1
View File
@@ -82,7 +82,8 @@ Core::Core(const CoreParams& params) :
tool_(Tool::kPointer),
addable_object_(Tool::kAddableEmpty),
snapping_(true),
core_params_(params)
core_params_(params),
pixel_sampling_users_(0)
{
// Store reference to this object, making the assumption that Core will only ever be made in
// main(). This will obviously break if not.
@@ -1206,6 +1207,25 @@ void Core::BrowseAutoRecoveries()
ard.exec();
}
void Core::RequestPixelSamplingInViewers(bool e)
{
if (e) {
if (pixel_sampling_users_ == 0) {
// Signal to start pixel sampling
emit ColorPickerEnabled(true);
}
pixel_sampling_users_++;
} else {
pixel_sampling_users_--;
if (pixel_sampling_users_ == 0) {
// Signal to end pixel sampling
emit ColorPickerEnabled(false);
}
}
}
bool Core::SaveProjectAs(Project* p)
{
QFileDialog fd(main_window_, tr("Save Project As"));
+19
View File
@@ -432,6 +432,8 @@ public slots:
void BrowseAutoRecoveries();
void RequestPixelSamplingInViewers(bool e);
signals:
/**
* @brief Signal emitted when a project is opened
@@ -472,6 +474,18 @@ signals:
*/
void OpenRecentListChanged();
/**
* @brief Enable mouse color sampling functionality on all viewers
*
* This can be slow, so we only turn it on when we need it.
*/
void ColorPickerEnabled(bool e);
/**
* @brief A viewer with color picked enabled has emitted a color
*/
void ColorPickerColorEmitted(const Color &reference, const Color &display);
private:
/**
* @brief Get the file filter than can be used with QFileDialog to open and save compatible projects
@@ -595,6 +609,11 @@ private:
*/
QVector<QUuid> autorecovered_projects_;
/**
* @brief How many widgets currently need pixel sampling access
*/
int pixel_sampling_users_;
private slots:
void SaveAutorecovery();
+1
View File
@@ -57,6 +57,7 @@ ColorDialog::ColorDialog(ColorManager* color_manager, const ManagedColor& start,
splitter->addWidget(value_area);
color_values_widget_ = new ColorValuesWidget(color_manager_);
color_values_widget_->IgnorePickFrom(this);
value_layout->addWidget(color_values_widget_);
chooser_ = new ColorSpaceChooser(color_manager_);
@@ -20,6 +20,8 @@
#include "pixelsamplerpanel.h"
#include "core.h"
namespace olive {
PixelSamplerPanel::PixelSamplerPanel(QWidget *parent) :
@@ -28,6 +30,9 @@ PixelSamplerPanel::PixelSamplerPanel(QWidget *parent) :
sampler_widget_ = new ManagedPixelSamplerWidget();
SetWidgetWithPadding(sampler_widget_);
connect(this, &PixelSamplerPanel::visibilityChanged, Core::instance(), &Core::RequestPixelSamplingInViewers);
connect(Core::instance(), &Core::ColorPickerColorEmitted, this, &PixelSamplerPanel::SetValues);
Retranslate();
}
-8
View File
@@ -72,14 +72,6 @@ void ViewerPanelBase::DisconnectTimeBasedPanel(TimeBasedPanel *panel)
disconnect(panel, &TimeBasedPanel::ShuttleRightRequested, this, &ViewerPanelBase::ShuttleRight);
}
void ViewerPanelBase::ConnectPixelSamplerPanel(PixelSamplerPanel *psp)
{
ViewerWidget* vw = static_cast<ViewerWidget*>(GetTimeBasedWidget());
connect(psp, &PixelSamplerPanel::visibilityChanged, vw, &ViewerWidget::SetSignalCursorColorEnabled);
connect(vw, &ViewerWidget::CursorColor, psp, &PixelSamplerPanel::SetValues);
}
void ViewerPanelBase::SetFullScreen(QScreen *screen)
{
static_cast<ViewerWidget*>(GetTimeBasedWidget())->SetFullScreen(screen);
-2
View File
@@ -47,8 +47,6 @@ public:
void DisconnectTimeBasedPanel(TimeBasedPanel* panel);
void ConnectPixelSamplerPanel(PixelSamplerPanel *psp);
/**
* @brief Wrapper for ViewerWidget::SetFullScreen()
*/
+14 -3
View File
@@ -53,15 +53,26 @@ void ColorButton::SetColor(const ManagedColor &c)
void ColorButton::ShowColorDialog()
{
ColorDialog cd(color_manager_, color_, this);
ColorDialog *cd = new ColorDialog(color_manager_, color_, this);
if (cd.exec() == QDialog::Accepted) {
color_ = cd.GetSelectedColor();
connect(cd, &ColorDialog::finished, this, &ColorButton::ColorDialogFinished);
cd->show();
}
void ColorButton::ColorDialogFinished(int e)
{
ColorDialog *cd = static_cast<ColorDialog*>(sender());
if (e == QDialog::Accepted) {
color_ = cd->GetSelectedColor();
UpdateColor();
emit ColorChanged(color_);
}
cd->deleteLater();
}
void ColorButton::UpdateColor()
+2
View File
@@ -45,6 +45,8 @@ signals:
private slots:
void ShowColorDialog();
void ColorDialogFinished(int e);
private:
void UpdateColor();
+213 -10
View File
@@ -21,8 +21,12 @@
#include "colorvalueswidget.h"
#include <QGridLayout>
#include <QMouseEvent>
#include <QTabWidget>
#include "config/config.h"
#include "core.h"
namespace olive {
ColorValuesWidget::ColorValuesWidget(ColorManager *manager, QWidget *parent) :
@@ -47,6 +51,12 @@ ColorValuesWidget::ColorValuesWidget(ColorManager *manager, QWidget *parent) :
preview_->setFixedHeight(fontMetrics().height() * 3 / 2);
preview_layout->addWidget(preview_);
color_picker_btn_ = new QPushButton(tr("Pick"));
color_picker_btn_->setCheckable(true);
connect(color_picker_btn_, &QPushButton::toggled, this, &ColorValuesWidget::ColorPickedBtnToggled);
connect(Core::instance(), &Core::ColorPickerColorEmitted, this, &ColorValuesWidget::SetReferenceColor);
preview_layout->addWidget(color_picker_btn_);
layout->addLayout(preview_layout);
}
@@ -54,7 +64,7 @@ ColorValuesWidget::ColorValuesWidget(ColorManager *manager, QWidget *parent) :
{
QTabWidget* tabs = new QTabWidget();
input_tab_ = new ColorValuesTab();
input_tab_ = new ColorValuesTab(true);
tabs->addTab(input_tab_, tr("Input"));
connect(input_tab_, &ColorValuesTab::ColorChanged, this, &ColorValuesWidget::UpdateValuesFromInput);
connect(input_tab_, &ColorValuesTab::ColorChanged, this, &ColorValuesWidget::ColorChanged);
@@ -92,6 +102,36 @@ void ColorValuesWidget::SetColorProcessor(ColorProcessorPtr input_to_ref, ColorP
preview_->SetColorProcessor(input_to_ref_, ref_to_display_);
}
bool ColorValuesWidget::eventFilter(QObject *watcher, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress) {
// Should signal to Core to stop pixel sampling and to us to remove our event filter
bool use_this_color = true;
foreach (QWidget *w, ignore_pick_from_) {
if (w->underMouse()) {
use_this_color = false;
break;
}
}
if (use_this_color) {
picker_end_color_ = GetColor();
}
color_picker_btn_->setChecked(false);
return true;
} else if (event->type() == QEvent::KeyPress) {
QKeyEvent *key_ev = static_cast<QKeyEvent*>(event);
if (key_ev->key() == Qt::Key_Escape) {
color_picker_btn_->setChecked(false);
return true;
}
}
return QWidget::eventFilter(watcher, event);
}
void ColorValuesWidget::SetColor(const Color &c)
{
input_tab_->SetColor(c);
@@ -100,6 +140,13 @@ void ColorValuesWidget::SetColor(const Color &c)
UpdateValuesFromInput();
}
void ColorValuesWidget::SetReferenceColor(const Color &c)
{
reference_tab_->SetColor(c);
UpdateValuesFromRef();
}
void ColorValuesWidget::UpdateValuesFromInput()
{
UpdateRefFromInput();
@@ -118,6 +165,24 @@ void ColorValuesWidget::UpdateValuesFromDisplay()
UpdateInputFromRef();
}
void ColorValuesWidget::ColorPickedBtnToggled(bool e)
{
Core::instance()->RequestPixelSamplingInViewers(e);
if (e) {
qApp->installEventFilter(this);
// Store current color in case it needs to be restored
picker_end_color_ = GetColor();
} else {
qApp->removeEventFilter(this);
// Restore original color (or use overridden color from eventFilter)
SetColor(picker_end_color_);
emit ColorChanged(picker_end_color_);
}
}
void ColorValuesWidget::UpdateInputFromRef()
{
if (ref_to_input_) {
@@ -157,16 +222,31 @@ void ColorValuesWidget::UpdateRefFromDisplay()
}
}
ColorValuesTab::ColorValuesTab(QWidget *parent) :
const double ColorValuesTab::kLegacyMultiplier = 255.0;
ColorValuesTab::ColorValuesTab(bool with_legacy_option, QWidget *parent) :
QWidget(parent)
{
QGridLayout* layout = new QGridLayout(this);
int row = 0;
if (with_legacy_option) {
legacy_box_ = new QCheckBox(tr("Use legacy (8-bit) values"));
legacy_box_->setChecked(Config::Current()[QStringLiteral("UseLegacyColorInInputTab")].toBool());
connect(legacy_box_, &QCheckBox::clicked, this, &ColorValuesTab::LegacyChanged);
layout->addWidget(legacy_box_, row, 0, 1, 2);
row++;
} else {
legacy_box_ = nullptr;
}
sliders_.resize(3);
layout->addWidget(new QLabel(tr("Red")), row, 0);
red_slider_ = CreateColorSlider();
sliders_[0] = red_slider_;
layout->addWidget(red_slider_, row, 1);
row++;
@@ -174,6 +254,7 @@ ColorValuesTab::ColorValuesTab(QWidget *parent) :
layout->addWidget(new QLabel(tr("Green")), row, 0);
green_slider_ = CreateColorSlider();
sliders_[1] = green_slider_;
layout->addWidget(green_slider_, row, 1);
row++;
@@ -181,28 +262,87 @@ ColorValuesTab::ColorValuesTab(QWidget *parent) :
layout->addWidget(new QLabel(tr("Blue")), row, 0);
blue_slider_ = CreateColorSlider();
sliders_[2] = blue_slider_;
layout->addWidget(blue_slider_, row, 1);
row++;
hex_lbl_ = new QLabel(tr("Hex"));
layout->addWidget(hex_lbl_, row, 0);
hex_slider_ = new StringSlider();
connect(hex_slider_, &StringSlider::ValueChanged, this, &ColorValuesTab::HexChanged);
layout->addWidget(hex_slider_, row, 1);
LegacyChanged(AreSlidersLegacyValues());
}
Color ColorValuesTab::GetColor() const
{
return Color(red_slider_->GetValue(),
green_slider_->GetValue(),
blue_slider_->GetValue());
return Color(GetRed(), GetGreen(), GetBlue());
}
void ColorValuesTab::SetColor(const Color &c)
{
red_slider_->SetValue(c.red());
green_slider_->SetValue(c.green());
blue_slider_->SetValue(c.blue());
SetRed(c.red());
SetGreen(c.green());
SetBlue(c.blue());
}
double ColorValuesTab::GetRed() const
{
return GetValueInternal(red_slider_);
}
double ColorValuesTab::GetGreen() const
{
return GetValueInternal(green_slider_);
}
double ColorValuesTab::GetBlue() const
{
return GetValueInternal(blue_slider_);
}
void ColorValuesTab::SetRed(double r)
{
SetValueInternal(red_slider_, r);
}
void ColorValuesTab::SetGreen(double g)
{
SetValueInternal(green_slider_, g);
}
void ColorValuesTab::SetBlue(double b)
{
SetValueInternal(blue_slider_, b);
}
double ColorValuesTab::GetValueInternal(FloatSlider *slider) const
{
double d = slider->GetValue();
if (AreSlidersLegacyValues()) {
d /= kLegacyMultiplier;
}
return d;
}
void ColorValuesTab::SetValueInternal(FloatSlider *slider, double v)
{
if (AreSlidersLegacyValues()) {
v *= kLegacyMultiplier;
}
slider->SetValue(v);
UpdateHex();
}
FloatSlider *ColorValuesTab::CreateColorSlider()
{
FloatSlider* fs = new FloatSlider();
fs->SetDragMultiplier(0.01);
fs->SetDecimalPlaces(5);
fs->SetLadderElementCount(1);
connect(fs, &FloatSlider::ValueChanged, this, &ColorValuesTab::SliderChanged);
return fs;
@@ -211,6 +351,69 @@ FloatSlider *ColorValuesTab::CreateColorSlider()
void ColorValuesTab::SliderChanged()
{
emit ColorChanged(GetColor());
UpdateHex();
}
void ColorValuesTab::LegacyChanged(bool legacy)
{
Config::Current()[QStringLiteral("UseLegacyColorInInputTab")] = legacy;
double legacy_multiplier = legacy ? kLegacyMultiplier : 1.0/kLegacyMultiplier;
int decimal_places = legacy ? 0 : 5;
double drag_multiplier = legacy ? 1.0 : 0.01;
foreach (FloatSlider *s, sliders_) {
s->SetValue(s->GetValue() * legacy_multiplier);
s->SetDecimalPlaces(decimal_places);
s->SetDragMultiplier(drag_multiplier);
}
hex_lbl_->setVisible(legacy);
hex_slider_->setVisible(legacy);
UpdateHex();
}
void ColorValuesTab::UpdateHex()
{
if (AreSlidersLegacyValues()) {
double r = red_slider_->GetValue();
double g = green_slider_->GetValue();
double b = blue_slider_->GetValue();
if (r > kLegacyMultiplier || g > kLegacyMultiplier || b > kLegacyMultiplier) {
hex_slider_->SetValue(tr("(Invalid)"));
} else {
uint32_t rgb = (uint8_t(r) << 16) | (uint8_t(g) << 8) | uint8_t(b);
hex_slider_->SetValue(QStringLiteral("%1").arg(rgb, 6, 16, QLatin1Char('0')).toUpper());
}
}
}
void ColorValuesTab::HexChanged(const QString &s)
{
bool ok;
uint32_t hex = s.toULong(&ok, 16);
if (ok) {
uint32_t r = (hex & 0xFF0000) >> 16;
uint32_t g = (hex & 0x00FF00) >> 8;
uint32_t b = (hex & 0x0000FF);
red_slider_->SetValue(r);
green_slider_->SetValue(g);
blue_slider_->SetValue(b);
emit ColorChanged(GetColor());
} else {
// Return to original value
UpdateHex();
}
}
bool ColorValuesTab::AreSlidersLegacyValues() const
{
return legacy_box_ && legacy_box_->isChecked();
}
}
+48 -1
View File
@@ -21,12 +21,15 @@
#ifndef COLORVALUESWIDGET_H
#define COLORVALUESWIDGET_H
#include <QCheckBox>
#include <QPushButton>
#include <QWidget>
#include "colorpreviewbox.h"
#include "node/color/colormanager/colormanager.h"
#include "render/color.h"
#include "widget/slider/floatslider.h"
#include "widget/slider/stringslider.h"
namespace olive {
@@ -34,25 +37,52 @@ class ColorValuesTab : public QWidget
{
Q_OBJECT
public:
ColorValuesTab(QWidget* parent = nullptr);
ColorValuesTab(bool with_legacy_option = false, QWidget* parent = nullptr);
Color GetColor() const;
void SetColor(const Color& c);
double GetRed() const;
double GetGreen() const;
double GetBlue() const;
void SetRed(double r);
void SetGreen(double g);
void SetBlue(double b);
signals:
void ColorChanged(const Color& c);
private:
static const double kLegacyMultiplier;
double GetValueInternal(FloatSlider *slider) const;
void SetValueInternal(FloatSlider *slider, double v);
bool AreSlidersLegacyValues() const;
FloatSlider* CreateColorSlider();
FloatSlider* red_slider_;
FloatSlider* green_slider_;
FloatSlider* blue_slider_;
QLabel *hex_lbl_;
StringSlider *hex_slider_;
QVector<FloatSlider*> sliders_;
QCheckBox *legacy_box_;
private slots:
void SliderChanged();
void LegacyChanged(bool e);
void UpdateHex();
void HexChanged(const QString &s);
};
class ColorValuesWidget : public QWidget
@@ -68,9 +98,18 @@ public:
ColorProcessorPtr display_to_ref,
ColorProcessorPtr ref_to_input);
virtual bool eventFilter(QObject *watcher, QEvent *event) override;
void IgnorePickFrom(QWidget *w)
{
ignore_pick_from_.append(w);
}
public slots:
void SetColor(const Color& c);
void SetReferenceColor(const Color& c);
signals:
void ColorChanged(const Color& c);
@@ -101,6 +140,12 @@ private:
ColorProcessorPtr ref_to_input_;
QPushButton *color_picker_btn_;
Color picker_end_color_;
QVector<QWidget *> ignore_pick_from_;
private slots:
void UpdateValuesFromInput();
@@ -108,6 +153,8 @@ private slots:
void UpdateValuesFromDisplay();
void ColorPickedBtnToggled(bool e);
};
}
+4
View File
@@ -36,6 +36,7 @@
#include "common/ratiodialog.h"
#include "common/timecodefunctions.h"
#include "config/config.h"
#include "core.h"
#include "node/project/project.h"
#include "render/rendermanager.h"
#include "task/taskmanager.h"
@@ -128,6 +129,9 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
instances_.append(this);
setAcceptDrops(true);
connect(Core::instance(), &Core::ColorPickerEnabled, this, &ViewerWidget::SetSignalCursorColorEnabled);
connect(this, &ViewerWidget::CursorColor, Core::instance(), &Core::ColorPickerColorEmitted);
}
ViewerWidget::~ViewerWidget()
-3
View File
@@ -114,9 +114,6 @@ MainWindow::MainWindow(QWidget *parent) :
sequence_viewer_panel_->ConnectTimeBasedPanel(param_panel_);
sequence_viewer_panel_->ConnectTimeBasedPanel(curve_panel_);
footage_viewer_panel_->ConnectPixelSamplerPanel(pixel_sampler_panel_);
sequence_viewer_panel_->ConnectPixelSamplerPanel(pixel_sampler_panel_);
UpdateTitle();
QMetaObject::invokeMethod(this, "SetDefaultLayout", Qt::QueuedConnection);