colordialog: add support for swatches

This commit is contained in:
itsmattkc
2022-09-25 14:27:15 -07:00
parent 490677fbca
commit c34416a478
8 changed files with 424 additions and 23 deletions
+39 -11
View File
@@ -40,9 +40,13 @@ ColorDialog::ColorDialog(ColorManager* color_manager, const ManagedColor& start,
splitter->setChildrenCollapsible(false);
layout->addWidget(splitter);
QWidget* wheel_area = new QWidget();
QHBoxLayout* wheel_layout = new QHBoxLayout(wheel_area);
splitter->addWidget(wheel_area);
QWidget* graphics_area = new QWidget();
splitter->addWidget(graphics_area);
QVBoxLayout *graphics_layout = new QVBoxLayout(graphics_area);
QHBoxLayout* wheel_layout = new QHBoxLayout();
graphics_layout->addLayout(wheel_layout);
color_wheel_ = new ColorWheelWidget();
wheel_layout->addWidget(color_wheel_);
@@ -51,6 +55,17 @@ ColorDialog::ColorDialog(ColorManager* color_manager, const ManagedColor& start,
hsv_value_gradient_->setFixedWidth(QtUtils::QFontMetricsWidth(fontMetrics(), QStringLiteral("HHH")));
wheel_layout->addWidget(hsv_value_gradient_);
QHBoxLayout *swatch_layout = new QHBoxLayout();
graphics_layout->addLayout(swatch_layout);
swatch_layout->addStretch();
swatch_ = new ColorSwatchChooser(color_manager_);
swatch_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
swatch_layout->addWidget(swatch_);
swatch_layout->addStretch();
QWidget* value_area = new QWidget();
QVBoxLayout* value_layout = new QVBoxLayout(value_area);
value_layout->setSpacing(0);
@@ -61,8 +76,6 @@ ColorDialog::ColorDialog(ColorManager* color_manager, const ManagedColor& start,
value_layout->addWidget(color_values_widget_);
chooser_ = new ColorSpaceChooser(color_manager_);
chooser_->set_input(start.color_input());
chooser_->set_output(start.color_output());
value_layout->addWidget(chooser_);
@@ -71,10 +84,16 @@ ColorDialog::ColorDialog(ColorManager* color_manager, const ManagedColor& start,
connect(color_wheel_, &ColorWheelWidget::SelectedColorChanged, color_values_widget_, &ColorValuesWidget::SetColor);
connect(color_wheel_, &ColorWheelWidget::SelectedColorChanged, hsv_value_gradient_, &ColorGradientWidget::SetSelectedColor);
connect(color_wheel_, &ColorWheelWidget::SelectedColorChanged, swatch_, &ColorSwatchChooser::SetCurrentColor);
connect(hsv_value_gradient_, &ColorGradientWidget::SelectedColorChanged, color_values_widget_, &ColorValuesWidget::SetColor);
connect(hsv_value_gradient_, &ColorGradientWidget::SelectedColorChanged, color_wheel_, &ColorWheelWidget::SetSelectedColor);
connect(hsv_value_gradient_, &ColorGradientWidget::SelectedColorChanged, swatch_, &ColorSwatchChooser::SetCurrentColor);
connect(color_values_widget_, &ColorValuesWidget::ColorChanged, hsv_value_gradient_, &ColorGradientWidget::SetSelectedColor);
connect(color_values_widget_, &ColorValuesWidget::ColorChanged, color_wheel_, &ColorWheelWidget::SetSelectedColor);
connect(color_values_widget_, &ColorValuesWidget::ColorChanged, swatch_, &ColorSwatchChooser::SetCurrentColor);
connect(swatch_, &ColorSwatchChooser::ColorClicked, hsv_value_gradient_, &ColorGradientWidget::SetSelectedColor);
connect(swatch_, &ColorSwatchChooser::ColorClicked, color_wheel_, &ColorWheelWidget::SetSelectedColor);
connect(swatch_, &ColorSwatchChooser::ColorClicked, color_values_widget_, &ColorValuesWidget::SetColor);
connect(color_wheel_, &ColorWheelWidget::DiameterChanged, hsv_value_gradient_, &ColorGradientWidget::setFixedHeight);
@@ -83,6 +102,20 @@ ColorDialog::ColorDialog(ColorManager* color_manager, const ManagedColor& start,
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
layout->addWidget(buttons);
SetColor(start);
connect(chooser_, &ColorSpaceChooser::ColorSpaceChanged, this, &ColorDialog::ColorSpaceChanged);
ColorSpaceChanged(chooser_->input(), chooser_->output());
// Set default size ratio to 2:1
resize(sizeHint().height() * 2, sizeHint().height());
}
void ColorDialog::SetColor(const ManagedColor &start)
{
chooser_->set_input(start.color_input());
chooser_->set_output(start.color_output());
Color managed_start;
if (start.color_input().isEmpty()) {
@@ -103,12 +136,7 @@ ColorDialog::ColorDialog(ColorManager* color_manager, const ManagedColor& start,
color_wheel_->SetSelectedColor(managed_start);
hsv_value_gradient_->SetSelectedColor(managed_start);
color_values_widget_->SetColor(managed_start);
connect(chooser_, &ColorSpaceChooser::ColorSpaceChanged, this, &ColorDialog::ColorSpaceChanged);
ColorSpaceChanged(chooser_->input(), chooser_->output());
// Set default size ratio to 2:1
resize(sizeHint().height() * 2, sizeHint().height());
swatch_->SetCurrentColor(managed_start);
}
ManagedColor ColorDialog::GetSelectedColor() const
+6
View File
@@ -28,6 +28,7 @@
#include "render/managedcolor.h"
#include "widget/colorwheel/colorgradientwidget.h"
#include "widget/colorwheel/colorspacechooser.h"
#include "widget/colorwheel/colorswatchchooser.h"
#include "widget/colorwheel/colorvalueswidget.h"
#include "widget/colorwheel/colorwheelwidget.h"
@@ -69,6 +70,9 @@ public:
ColorTransform GetColorSpaceOutput() const;
public slots:
void SetColor(const ManagedColor &c);
private:
ColorManager* color_manager_;
@@ -82,6 +86,8 @@ private:
ColorSpaceChooser* chooser_;
ColorSwatchChooser *swatch_;
private slots:
void ColorSpaceChanged(const QString& input, const ColorTransform &output);
+4 -2
View File
@@ -24,14 +24,16 @@
namespace olive {
ColorButton::ColorButton(ColorManager* color_manager, QWidget *parent) :
ColorButton::ColorButton(ColorManager* color_manager, bool show_dialog_on_click, QWidget *parent) :
QPushButton(parent),
color_manager_(color_manager),
color_processor_(nullptr)
{
setAutoFillBackground(true);
connect(this, &ColorButton::clicked, this, &ColorButton::ShowColorDialog);
if (show_dialog_on_click) {
connect(this, &ColorButton::clicked, this, &ColorButton::ShowColorDialog);
}
SetColor(Color(1.0f, 1.0f, 1.0f));
}
+5 -1
View File
@@ -32,7 +32,11 @@ class ColorButton : public QPushButton
{
Q_OBJECT
public:
ColorButton(ColorManager* color_manager, QWidget* parent = nullptr);
ColorButton(ColorManager* color_manager, bool show_dialog_on_click, QWidget* parent = nullptr);
ColorButton(ColorManager* color_manager, QWidget* parent = nullptr) :
ColorButton(color_manager, true, parent)
{
}
const ManagedColor& GetColor() const;
+2
View File
@@ -22,6 +22,8 @@ set(OLIVE_SOURCES
widget/colorwheel/colorpreviewbox.cpp
widget/colorwheel/colorspacechooser.h
widget/colorwheel/colorspacechooser.cpp
widget/colorwheel/colorswatchchooser.h
widget/colorwheel/colorswatchchooser.cpp
widget/colorwheel/colorswatchwidget.h
widget/colorwheel/colorswatchwidget.cpp
widget/colorwheel/colorvalueswidget.h
@@ -0,0 +1,223 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2022 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 "colorswatchchooser.h"
#include <QGridLayout>
#include "common/filefunctions.h"
#include "widget/menu/menu.h"
namespace olive {
const int kDefaultColorCount = 16;
const Color kDefaultColors[kDefaultColorCount] = {
Color(1.0, 1.0, 1.0),
Color(1.0, 1.0, 0.0),
Color(1.0, 0.5, 0.0),
Color(1.0, 0.0, 0.0),
Color(1.0, 0.0, 1.0),
Color(0.5, 0.0, 1.0),
Color(0.0, 0.0, 1.0),
Color(0.0, 0.5, 1.0),
Color(0.0, 1.0, 0.0),
Color(0.0, 0.5, 0.0),
Color(0.5, 0.25, 0.0),
Color(0.75, 0.5, 0.25),
Color(0.75, 0.75, 0.75),
Color(0.5, 0.5, 0.5),
Color(0.25, 0.25, 0.25),
Color(0.0, 0.0, 0.0)
};
ColorSwatchChooser::ColorSwatchChooser(ColorManager *manager, QWidget *parent) :
QWidget(parent)
{
auto layout = new QGridLayout(this);
for (int x=0; x<kColCount; x++) {
for (int y=0; y<kRowCount; y++) {
// Create button
auto b = new ColorButton(manager, false);
b->setFixedWidth(b->sizeHint().height()/2*3);
b->setContextMenuPolicy(Qt::CustomContextMenu);
layout->addWidget(b, y, x);
// Save button in buttons array
int btn_index = x + kColCount*y;
buttons_[btn_index] = b;
// Set default color
SetDefaultColor(btn_index);
// Connect clicks
connect(b, &ColorButton::clicked, this, &ColorSwatchChooser::HandleButtonClick);
connect(b, &ColorButton::customContextMenuRequested, this, &ColorSwatchChooser::HandleContextMenu);
}
}
LoadSwatches();
}
void ColorSwatchChooser::SetDefaultColor(int index)
{
if (index < kDefaultColorCount) {
buttons_[index]->SetColor(kDefaultColors[index]);
} else {
buttons_[index]->SetColor(Color(1.0, 1.0, 1.0));
}
}
void ColorSwatchChooser::HandleButtonClick()
{
auto b = static_cast<ColorButton*>(sender());
emit ColorClicked(b->GetColor());
SetCurrentColor(b->GetColor());
}
void ColorSwatchChooser::HandleContextMenu()
{
Menu m(this);
auto save_action = m.addAction(tr("Save Color Here"));
connect(save_action, &QAction::triggered, this, &ColorSwatchChooser::SaveCurrentColor);
m.addSeparator();
auto reset_action = m.addAction(tr("Reset To Default"));
connect(reset_action, &QAction::triggered, this, &ColorSwatchChooser::ResetMenuButton);
menu_btn_ = static_cast<ColorButton*>(sender());
m.exec(QCursor::pos());
}
void ColorSwatchChooser::SaveCurrentColor()
{
menu_btn_->SetColor(current_);
SaveSwatches();
}
void ColorSwatchChooser::ResetMenuButton()
{
for (int i=0; i<kBtnCount; i++) {
if (buttons_[i] == menu_btn_) {
SetDefaultColor(i);
break;
}
}
}
QString ColorSwatchChooser::GetSwatchFilename()
{
return QDir(FileFunctions::GetConfigurationLocation()).filePath(QStringLiteral("swatch"));
}
void ColorSwatchChooser::LoadSwatches()
{
QFile f(GetSwatchFilename());
if (f.open(QFile::ReadOnly)) {
QDataStream d(&f);
uint version;
d >> version;
if (version == 1) {
int index = 0;
while (index < kBtnCount && !d.atEnd()) {
Color::DataType r;
QString s;
ManagedColor c;
ColorTransform t;
bool is_display;
c.set_alpha(1.0);
d >> r;
c.set_red(r);
d >> r;
c.set_green(r);
d >> r;
c.set_blue(r);
d >> s;
c.set_color_input(s);
d >> is_display;
if (is_display) {
QString display, view, look;
d >> display;
d >> view;
d >> look;
c.set_color_output(ColorTransform(display, view, look));
} else {
d >> s;
c.set_color_output(ColorTransform(s));
}
buttons_[index]->SetColor(c);
index++;
}
}
f.close();
}
}
void ColorSwatchChooser::SaveSwatches()
{
QString fn = GetSwatchFilename();
QFile f(fn);
if (f.open(QFile::WriteOnly)) {
QDataStream d(&f);
const uint version = 1;
d << version;
for (int i=0; i<kBtnCount; i++) {
const ManagedColor &c = buttons_[i]->GetColor();
d << c.red();
d << c.green();
d << c.blue();
d << c.color_input();
d << c.color_output().is_display();
if (c.color_output().is_display()) {
d << c.color_output().display();
d << c.color_output().view();
d << c.color_output().look();
} else {
d << c.color_output().output();
}
}
f.close();
} else {
qCritical() << "Failed to open swatch file" << fn << "for writing";
}
}
}
@@ -0,0 +1,73 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2022 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 COLORSWATCHCHOOSER_H
#define COLORSWATCHCHOOSER_H
#include "node/color/colormanager/colormanager.h"
#include "widget/colorbutton/colorbutton.h"
namespace olive {
class ColorSwatchChooser : public QWidget
{
Q_OBJECT
public:
ColorSwatchChooser(ColorManager *manager, QWidget *parent = nullptr);
public slots:
void SetCurrentColor(const ManagedColor &c)
{
current_ = c;
}
signals:
void ColorClicked(const ManagedColor &c);
private:
void SetDefaultColor(int index);
static QString GetSwatchFilename();
void LoadSwatches();
void SaveSwatches();
static const int kRowCount = 4;
static const int kColCount = 8;
static const int kBtnCount = kRowCount*kColCount;
ColorButton *buttons_[kBtnCount];
ManagedColor current_;
ColorButton *menu_btn_;
private slots:
void HandleButtonClick();
void HandleContextMenu();
void SaveCurrentColor();
void ResetMenuButton();
};
}
#endif // COLORSWATCHCHOOSER_H
+72 -9
View File
@@ -270,14 +270,16 @@ ColorValuesTab::ColorValuesTab(bool with_legacy_option, QWidget *parent) :
row++;
hex_lbl_ = new QLabel(tr("Hex"));
hex_lbl_ = new QLabel(tr("Web"));
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());
if (legacy_box_) {
LegacyChanged(AreSlidersLegacyValues());
}
}
Color ColorValuesTab::GetColor() const
@@ -371,11 +373,20 @@ void ColorValuesTab::LegacyChanged(bool legacy)
s->SetDragMultiplier(drag_multiplier);
}
hex_lbl_->setVisible(legacy);
hex_slider_->setVisible(legacy);
UpdateHex();
}
QString RGBValToString(double d)
{
QString s = QString::number(d);
if (!s.contains('.')) {
s.append(QStringLiteral(".0"));
}
return s;
}
void ColorValuesTab::UpdateHex()
{
if (AreSlidersLegacyValues()) {
@@ -390,9 +401,39 @@ void ColorValuesTab::UpdateHex()
hex_slider_->SetValue(QStringLiteral("%1").arg(rgb, 6, 16, QLatin1Char('0')).toUpper());
}
} else {
hex_slider_->SetValue(QStringLiteral("rgb(%1, %2, %3)").arg(RGBValToString(red_slider_->GetValue()), RGBValToString(green_slider_->GetValue()), RGBValToString(blue_slider_->GetValue())));
}
}
bool ParseRGBString(QString s, double *r, double *g, double *b)
{
// Trim whitespace
s = s.trimmed();
s.remove(QStringLiteral("rgba"), Qt::CaseInsensitive);
s.remove(QStringLiteral("rgb"), Qt::CaseInsensitive);
s.remove('(');
s.remove(')');
QStringList vals = s.split(',');
if (vals.size() < 3) {
return false;
}
bool ok;
*r = vals.at(0).toDouble(&ok);
if (!ok) return false;
*g = vals.at(1).toDouble(&ok);
if (!ok) return false;
*b = vals.at(2).toDouble(&ok);
if (!ok) return false;
return true;
}
void ColorValuesTab::HexChanged(const QString &s)
{
bool ok;
@@ -403,15 +444,37 @@ void ColorValuesTab::HexChanged(const QString &s)
uint32_t g = (hex & 0x00FF00) >> 8;
uint32_t b = (hex & 0x0000FF);
red_slider_->SetValue(r);
green_slider_->SetValue(g);
blue_slider_->SetValue(b);
if (AreSlidersLegacyValues()) {
red_slider_->SetValue(r);
green_slider_->SetValue(g);
blue_slider_->SetValue(b);
} else {
red_slider_->SetValue(double(r)/kLegacyMultiplier);
green_slider_->SetValue(double(g)/kLegacyMultiplier);
blue_slider_->SetValue(double(b)/kLegacyMultiplier);
}
emit ColorChanged(GetColor());
} else {
// Return to original value
UpdateHex();
// Attempt to parse rgb/rgba
double r, g, b;
if (ParseRGBString(s, &r, &g, &b)) {
if (AreSlidersLegacyValues()) {
red_slider_->SetValue(r*kLegacyMultiplier);
green_slider_->SetValue(g*kLegacyMultiplier);
blue_slider_->SetValue(b*kLegacyMultiplier);
} else {
red_slider_->SetValue(r);
green_slider_->SetValue(g);
blue_slider_->SetValue(b);
}
emit ColorChanged(GetColor());
}
}
// Conform string to our formatting
UpdateHex();
}
bool ColorValuesTab::AreSlidersLegacyValues() const