diff --git a/src/assets/assetpanel.cpp b/src/assets/assetpanel.cpp index c005e36ff..35eb1183b 100644 --- a/src/assets/assetpanel.cpp +++ b/src/assets/assetpanel.cpp @@ -1,381 +1,387 @@ /*************************************************************************** * Copyright (C) 2017 by Nicolas Carion * * This file is part of Kdenlive. See www.kdenlive.org. * * * * 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 2 of the License, or * * (at your option) version 3 or any later version accepted by the * * membership of KDE e.V. (or its successor approved by the membership * * of KDE e.V.), which shall act as a proxy defined in Section 14 of * * version 3 of the license. * * * * 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 . * ***************************************************************************/ #include "assetpanel.hpp" #include "core.h" #include "definitions.h" #include "effects/effectstack/model/effectitemmodel.hpp" #include "effects/effectstack/model/effectstackmodel.hpp" #include "effects/effectstack/view/effectstackview.hpp" #include "kdenlivesettings.h" #include "model/assetparametermodel.hpp" #include "transitions/transitionsrepository.hpp" #include "transitions/view/transitionstackview.hpp" #include "view/assetparameterview.hpp" #include #include #include #include #include #include #include #include #include #include #include #include AssetPanel::AssetPanel(QWidget *parent) : QWidget(parent) , m_lay(new QVBoxLayout(this)) , m_assetTitle(new KSqueezedTextLabel(this)) , m_container(new QWidget(this)) , m_transitionWidget(new TransitionStackView(this)) , m_effectStackWidget(new EffectStackView(this)) { auto *buttonToolbar = new QToolBar(this); m_titleAction = buttonToolbar->addWidget(m_assetTitle); int size = style()->pixelMetric(QStyle::PM_SmallIconSize); QSize iconSize(size, size); buttonToolbar->setIconSize(iconSize); // Edit composition button m_switchCompoButton = new QComboBox(this); m_switchCompoButton->setFrame(false); auto allTransitions = TransitionsRepository::get()->getNames(); for (const auto &transition : allTransitions) { m_switchCompoButton->addItem(transition.second, transition.first); } connect(m_switchCompoButton, static_cast(&QComboBox::activated), [&]() { if (m_transitionWidget->stackOwner().first == ObjectType::TimelineComposition) { emit switchCurrentComposition(m_transitionWidget->stackOwner().second, m_switchCompoButton->currentData().toString()); } }); m_switchCompoButton->setToolTip(i18n("Change composition type")); m_switchAction = buttonToolbar->addWidget(m_switchCompoButton); m_switchAction->setVisible(false); // spacer QWidget *empty = new QWidget(); empty->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum); buttonToolbar->addWidget(empty); m_switchBuiltStack = new QToolButton(this); m_switchBuiltStack->setIcon(QIcon::fromTheme(QStringLiteral("adjustlevels"))); m_switchBuiltStack->setToolTip(i18n("Adjust clip")); m_switchBuiltStack->setCheckable(true); m_switchBuiltStack->setChecked(KdenliveSettings::showbuiltstack()); m_switchBuiltStack->setVisible(false); // connect(m_switchBuiltStack, &QToolButton::toggled, m_effectStackWidget, &EffectStackView::switchBuiltStack); buttonToolbar->addWidget(m_switchBuiltStack); m_splitButton = new KDualAction(i18n("Normal view"), i18n("Compare effect"), this); m_splitButton->setActiveIcon(QIcon::fromTheme(QStringLiteral("view-right-close"))); m_splitButton->setInactiveIcon(QIcon::fromTheme(QStringLiteral("view-split-left-right"))); m_splitButton->setToolTip(i18n("Compare effect")); m_splitButton->setVisible(false); connect(m_splitButton, &KDualAction::activeChangedByUser, this, &AssetPanel::processSplitEffect); buttonToolbar->addAction(m_splitButton); m_enableStackButton = new KDualAction(i18n("Effects disabled"), i18n("Effects enabled"), this); m_enableStackButton->setInactiveIcon(QIcon::fromTheme(QStringLiteral("hint"))); m_enableStackButton->setActiveIcon(QIcon::fromTheme(QStringLiteral("visibility"))); connect(m_enableStackButton, &KDualAction::activeChangedByUser, this, &AssetPanel::enableStack); m_enableStackButton->setVisible(false); buttonToolbar->addAction(m_enableStackButton); m_timelineButton = new KDualAction(i18n("Hide keyframes"), i18n("Display keyframes in timeline"), this); m_timelineButton->setInactiveIcon(QIcon::fromTheme(QStringLiteral("adjustlevels"))); m_timelineButton->setActiveIcon(QIcon::fromTheme(QStringLiteral("adjustlevels"))); m_timelineButton->setToolTip(i18n("Display keyframes in timeline")); m_timelineButton->setVisible(false); connect(m_timelineButton, &KDualAction::activeChangedByUser, this, &AssetPanel::showKeyframes); buttonToolbar->addAction(m_timelineButton); m_lay->addWidget(buttonToolbar); m_lay->setContentsMargins(0, 0, 0, 0); m_lay->setSpacing(0); auto *lay = new QVBoxLayout(m_container); lay->setContentsMargins(0, 0, 0, 0); lay->addWidget(m_transitionWidget); lay->addWidget(m_effectStackWidget); auto *sc = new QScrollArea; sc->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); sc->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); sc->setFrameStyle(QFrame::NoFrame); sc->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding)); m_container->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding)); sc->setWidgetResizable(true); m_lay->addWidget(sc); sc->setWidget(m_container); m_transitionWidget->setVisible(false); m_effectStackWidget->setVisible(false); updatePalette(); connect(m_effectStackWidget, &EffectStackView::seekToPos, this, &AssetPanel::seekToPos); connect(m_effectStackWidget, &EffectStackView::reloadEffect, this, &AssetPanel::reloadEffect); connect(m_transitionWidget, &TransitionStackView::seekToTransPos, this, &AssetPanel::seekToPos); connect(m_effectStackWidget, &EffectStackView::updateEnabledState, [this]() { m_enableStackButton->setActive(m_effectStackWidget->isStackEnabled()); }); } void AssetPanel::showTransition(int tid, const std::shared_ptr &transitionModel) { Q_UNUSED(tid) ObjectId id = transitionModel->getOwnerId(); if (m_transitionWidget->stackOwner() == id) { // already on this effect stack, do nothing return; } clear(); QString transitionId = transitionModel->getAssetId(); m_switchCompoButton->setCurrentIndex(m_switchCompoButton->findData(transitionId)); m_switchAction->setVisible(true); m_titleAction->setVisible(false); m_assetTitle->clear(); m_transitionWidget->setVisible(true); m_timelineButton->setVisible(true); m_enableStackButton->setVisible(false); m_transitionWidget->setModel(transitionModel, QSize(), true); } void AssetPanel::showEffectStack(const QString &itemName, const std::shared_ptr &effectsModel, QSize frameSize, bool showKeyframes) { if (effectsModel == nullptr) { // Item is not ready m_splitButton->setVisible(false); m_enableStackButton->setVisible(false); clear(); return; } ObjectId id = effectsModel->getOwnerId(); if (m_effectStackWidget->stackOwner() == id) { // already on this effect stack, do nothing // Disable split effect in case clip was moved if (id.first == ObjectType::TimelineClip && m_splitButton->isActive()) { m_splitButton->setActive(false); processSplitEffect(false); } return; } clear(); QString title; bool showSplit = false; bool enableKeyframes = false; switch (id.first) { case ObjectType::TimelineClip: title = i18n("%1 effects", itemName); showSplit = true; enableKeyframes = true; break; case ObjectType::TimelineComposition: title = i18n("%1 parameters", itemName); enableKeyframes = true; break; case ObjectType::TimelineTrack: title = i18n("Track %1 effects", itemName); // TODO: track keyframes // enableKeyframes = true; break; case ObjectType::BinClip: title = i18n("Bin %1 effects", itemName); showSplit = true; break; default: title = itemName; break; } m_assetTitle->setText(title); m_titleAction->setVisible(true); m_splitButton->setVisible(showSplit); m_enableStackButton->setVisible(id.first != ObjectType::TimelineComposition); m_enableStackButton->setActive(effectsModel->isStackEnabled()); if (showSplit) { m_splitButton->setEnabled(effectsModel->rowCount() > 0); QObject::connect(effectsModel.get(), &EffectStackModel::dataChanged, [&]() { if (m_effectStackWidget->isEmpty()) { m_splitButton->setActive(false); } m_splitButton->setEnabled(!m_effectStackWidget->isEmpty()); }); } m_timelineButton->setVisible(enableKeyframes); m_timelineButton->setActive(showKeyframes); // Disable built stack until properly implemented // m_switchBuiltStack->setVisible(true); m_effectStackWidget->setVisible(true); m_effectStackWidget->setModel(effectsModel, frameSize); } void AssetPanel::clearAssetPanel(int itemId) { ObjectId id = m_effectStackWidget->stackOwner(); if (id.first == ObjectType::TimelineClip && id.second == itemId) { clear(); } else { id = m_transitionWidget->stackOwner(); if (id.first == ObjectType::TimelineComposition && id.second == itemId) { clear(); } } } void AssetPanel::clear() { if (m_splitButton->isActive()) { m_splitButton->setActive(false); processSplitEffect(false); } m_switchAction->setVisible(false); m_transitionWidget->setVisible(false); m_transitionWidget->unsetModel(); m_effectStackWidget->setVisible(false); m_splitButton->setVisible(false); m_timelineButton->setVisible(false); m_switchBuiltStack->setVisible(false); m_effectStackWidget->unsetModel(); m_assetTitle->setText(QString()); } void AssetPanel::updatePalette() { QString styleSheet = getStyleSheet(); setStyleSheet(styleSheet); m_transitionWidget->setStyleSheet(styleSheet); m_effectStackWidget->setStyleSheet(styleSheet); } // static const QString AssetPanel::getStyleSheet() { KColorScheme scheme(QApplication::palette().currentColorGroup(), KColorScheme::View); QColor selected_bg = scheme.decoration(KColorScheme::FocusColor).color(); QColor hgh = KColorUtils::mix(QApplication::palette().window().color(), selected_bg, 0.2); QColor hover_bg = scheme.decoration(KColorScheme::HoverColor).color(); QColor light_bg = scheme.shade(KColorScheme::LightShade); QColor alt_bg = scheme.background(KColorScheme::NormalBackground).color(); QString stylesheet; // effect background stylesheet.append(QStringLiteral("QFrame#decoframe {border-bottom:2px solid " "palette(mid);background: transparent} QFrame#decoframe[active=\"true\"] {background: %1;}") .arg(hgh.name())); // effect in group background stylesheet.append( QStringLiteral("QFrame#decoframesub {border-top:1px solid palette(light);} QFrame#decoframesub[active=\"true\"] {background: %1;}").arg(hgh.name())); // group background stylesheet.append(QStringLiteral("QFrame#decoframegroup {border:2px solid palette(dark);margin:0px;margin-top:2px;} ")); // effect title bar stylesheet.append(QStringLiteral("QFrame#frame {margin-bottom:2px;} QFrame#frame[target=\"true\"] " "{background: palette(highlight);}")); // group effect title bar stylesheet.append(QStringLiteral("QFrame#framegroup {background: palette(dark);} " "QFrame#framegroup[target=\"true\"] {background: palette(highlight);} ")); // draggable effect bar content stylesheet.append(QStringLiteral("QProgressBar::chunk:horizontal {background: palette(button);border-top-left-radius: 4px;border-bottom-left-radius: 4px;} " "QProgressBar::chunk:horizontal#dragOnly {background: %1;border-top-left-radius: 4px;border-bottom-left-radius: 4px;} " "QProgressBar::chunk:horizontal:hover {background: %2;}") .arg(alt_bg.name(), selected_bg.name())); // draggable effect bar stylesheet.append(QStringLiteral("QProgressBar:horizontal {border: 1px solid palette(dark);border-top-left-radius: 4px;border-bottom-left-radius: " "4px;border-right:0px;background:%3;padding: 0px;text-align:left center} QProgressBar:horizontal:disabled {border: 1px " "solid palette(button)} QProgressBar:horizontal#dragOnly {background: %3} QProgressBar:horizontal[inTimeline=\"true\"] { " "border: 1px solid %1;border-right: 0px;background: %2;padding: 0px;text-align:left center } " "QProgressBar::chunk:horizontal[inTimeline=\"true\"] {background: %1;}") .arg(hover_bg.name(), light_bg.name(), alt_bg.name())); // spin box for draggable widget stylesheet.append( QStringLiteral("QAbstractSpinBox#dragBox {border: 1px solid palette(dark);border-top-right-radius: 4px;border-bottom-right-radius: " "4px;padding-right:0px;} QAbstractSpinBox::down-button#dragBox {width:0px;padding:0px;} QAbstractSpinBox:disabled#dragBox {border: 1px " "solid palette(button);} QAbstractSpinBox::up-button#dragBox {width:0px;padding:0px;} QAbstractSpinBox[inTimeline=\"true\"]#dragBox { " "border: 1px solid %1;} QAbstractSpinBox:hover#dragBox {border: 1px solid %2;} ") .arg(hover_bg.name(), selected_bg.name())); + // minimal double edit + stylesheet.append( + QStringLiteral("QAbstractSpinBox#dragMinimal {border: 0px " + ";padding-right:0px; background-color:transparent} QAbstractSpinBox::down-button#dragMinimal {width:0px;padding:0px;} QAbstractSpinBox:disabled#dragMinimal {border: 0px;; background-color:transparent " + ";} QAbstractSpinBox::up-button#dragMinimal {width:0px;padding:0px;}") + ); // group editable labels stylesheet.append(QStringLiteral("MyEditableLabel { background-color: transparent; color: palette(bright-text); border-radius: 2px;border: 1px solid " "transparent;} MyEditableLabel:hover {border: 1px solid palette(highlight);} ")); // transparent qcombobox stylesheet.append(QStringLiteral("QComboBox { background-color: transparent;} ")); return stylesheet; } void AssetPanel::processSplitEffect(bool enable) { ObjectType id = m_effectStackWidget->stackOwner().first; if (id == ObjectType::TimelineClip) { emit doSplitEffect(enable); } else if (id == ObjectType::BinClip) { emit doSplitBinEffect(enable); } } void AssetPanel::showKeyframes(bool enable) { if (m_transitionWidget->isVisible()) { pCore->showClipKeyframes(m_transitionWidget->stackOwner(), enable); } else { pCore->showClipKeyframes(m_effectStackWidget->stackOwner(), enable); } } ObjectId AssetPanel::effectStackOwner() { if (m_transitionWidget->isVisible()) { return m_transitionWidget->stackOwner(); } if (!m_effectStackWidget->isVisible()) { return ObjectId(ObjectType::NoItem, -1); } return m_effectStackWidget->stackOwner(); } bool AssetPanel::addEffect(const QString &effectId) { if (!m_effectStackWidget->isVisible()) { return false; } return m_effectStackWidget->addEffect(effectId); } void AssetPanel::enableStack(bool enable) { if (!m_effectStackWidget->isVisible()) { return; } m_effectStackWidget->enableStack(enable); } void AssetPanel::deleteCurrentEffect() { if (m_effectStackWidget->isVisible()) { m_effectStackWidget->removeCurrentEffect(); } } diff --git a/src/assets/view/widgets/colorwheel.cpp b/src/assets/view/widgets/colorwheel.cpp index 673a36b68..6ae96d263 100644 --- a/src/assets/view/widgets/colorwheel.cpp +++ b/src/assets/view/widgets/colorwheel.cpp @@ -1,398 +1,586 @@ /* * Copyright (c) 2013 Meltytech, LLC * Author: Dan Dennedy * Some ideas came from Qt-Plus: https://github.com/liuyanghejerry/Qt-Plus * and Steinar Gunderson's Movit demo app. * * 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 . */ #include "colorwheel.h" + +#include +#include +#include +#include +#include +#include + #include #include NegQColor NegQColor::fromHsvF(qreal h, qreal s, qreal l, qreal a) { NegQColor color; color.qcolor = QColor::fromHsvF(h, s, l < 0 ? -l : l, a); color.sign_r = l < 0 ? -1 : 1; color.sign_g = l < 0 ? -1 : 1; color.sign_b = l < 0 ? -1 : 1; return color; } NegQColor NegQColor::fromRgbF(qreal r, qreal g, qreal b, qreal a) { NegQColor color; color.qcolor = QColor::fromRgbF(r < 0 ? -r : r, g < 0 ? -g : g, b < 0 ? -b : b, a); color.sign_r = r < 0 ? -1 : 1; color.sign_g = g < 0 ? -1 : 1; color.sign_b = b < 0 ? -1 : 1; return color; } -qreal NegQColor::redF() +qreal NegQColor::redF() const { return qcolor.redF() * sign_r; } -qreal NegQColor::greenF() +void NegQColor::setRedF(qreal val) +{ + sign_r = val < 0 ? -1 : 1; + qcolor.setRedF(val * sign_r); +} + +qreal NegQColor::greenF() const { return qcolor.greenF() * sign_g; } -qreal NegQColor::blueF() +void NegQColor::setGreenF(qreal val) +{ + sign_g = val < 0 ? -1 : 1; + qcolor.setGreenF(val * sign_g); +} + +qreal NegQColor::blueF() const { return qcolor.blueF() * sign_b; } -qreal NegQColor::valueF() +void NegQColor::setBlueF(qreal val) +{ + sign_b = val < 0 ? -1 : 1; + qcolor.setBlueF(val * sign_b); +} + +qreal NegQColor::valueF() const { return qcolor.valueF() * sign_g; } -int NegQColor::hue() +void NegQColor::setValueF(qreal val) +{ + qcolor = QColor::fromHsvF(hueF(), saturationF(), val < 0 ? -val : val, 1.); + sign_r = val < 0 ? -1 : 1; + sign_g = val < 0 ? -1 : 1; + sign_b = val < 0 ? -1 : 1; +} + +int NegQColor::hue() const { return qcolor.hue(); } -qreal NegQColor::hueF() +qreal NegQColor::hueF() const { return qcolor.hueF(); } -qreal NegQColor::saturationF() +qreal NegQColor::saturationF() const { return qcolor.saturationF(); } -ColorWheel::ColorWheel(QString id, QString name, NegQColor color, QWidget *parent) +WheelContainer::WheelContainer(QString id, QString name, NegQColor color, int unitSize, QWidget *parent) : QWidget(parent) , m_id(std::move(id)) , m_isMouseDown(false) - , m_margin(5) + , m_margin(0) , m_color(std::move(color)) , m_isInWheel(false) , m_isInSquare(false) + , m_unitSize(unitSize) , m_name(std::move(name)) { - QFontInfo info(font()); - m_unitSize = info.pixelSize(); m_initialSize = QSize(m_unitSize * 11, m_unitSize * 11); m_sliderWidth = m_unitSize * 1.5; resize(m_initialSize); setMinimumSize(m_initialSize * .4); - setMaximumSize(m_initialSize); + setMaximumSize(m_initialSize * 1.5); setCursor(Qt::CrossCursor); } -void ColorWheel::setFactorDefaultZero(qreal factor, qreal defvalue, qreal zero) + +void WheelContainer::setFactorDefaultZero(qreal factor, qreal defvalue, qreal zero) { m_sizeFactor = factor; m_defaultValue = defvalue; m_zeroShift = zero; } -NegQColor ColorWheel::color() const +NegQColor WheelContainer::color() const { return m_color; } -void ColorWheel::setColor(const NegQColor &color) +void WheelContainer::setColor(QList values) { + const NegQColor color = NegQColor::fromRgbF(values.at(0) / m_sizeFactor, values.at(1) / m_sizeFactor, values.at(2) / m_sizeFactor); m_color = color; update(); } -int ColorWheel::wheelSize() const +void WheelContainer::setRedColor(double value) { - return qMin(width() - m_sliderWidth, height() - m_unitSize); + m_color.setRedF(value / m_sizeFactor); + emit colorChange(m_color); + update(); } -NegQColor ColorWheel::colorForPoint(const QPointF &point) +void WheelContainer::setGreenColor(double value) +{ + m_color.setGreenF(value / m_sizeFactor); + emit colorChange(m_color); + update(); +} + +void WheelContainer::setBlueColor(double value) +{ + m_color.setBlueF(value / m_sizeFactor); + emit colorChange(m_color); + update(); +} + +int WheelContainer::wheelSize() const +{ + return qMin(width() - m_sliderWidth, height()); +} + +NegQColor WheelContainer::colorForPoint(const QPointF &point) { if (!m_image.valid(point.toPoint())) { return NegQColor(); } if (m_isInWheel) { qreal w = wheelSize(); qreal xf = qreal(point.x()) / w; qreal yf = 1.0 - qreal(point.y()) / w; qreal xp = 2.0 * xf - 1.0; qreal yp = 2.0 * yf - 1.0; qreal rad = qMin(hypot(xp, yp), 1.0); qreal theta = qAtan2(yp, xp); theta -= 105.0 / 360.0 * 2.0 * M_PI; if (theta < 0.0) { theta += 2.0 * M_PI; } qreal hue = (theta * 180.0 / M_PI) / 360.0; return NegQColor::fromHsvF(hue, rad, m_color.valueF()); } if (m_isInSquare) { qreal value = 1.0 - qreal(point.y() - m_margin) / (wheelSize() - m_margin * 2); if (!qFuzzyCompare(m_zeroShift, 0.)) { value = value - m_zeroShift; } return NegQColor::fromHsvF(m_color.hueF(), m_color.saturationF(), value); } return {}; } -QSize ColorWheel::sizeHint() const +QSize WheelContainer::sizeHint() const { return m_initialSize * .8; } -QSize ColorWheel::minimumSizeHint() const + +QSize WheelContainer::minimumSizeHint() const { return m_initialSize * .4; } -void ColorWheel::mousePressEvent(QMouseEvent *event) +void WheelContainer::wheelEvent(QWheelEvent *event) +{ + if (m_sliderRegion.contains(event->pos())) { + double y = m_color.valueF(); + if (event->modifiers() & Qt::ShiftModifier) { + y += event->angleDelta().y() > 0 ? 0.002 : -0.002; + } else { + y += event->angleDelta().y() > 0 ? 0.04 : -0.04; + } + m_color.setValueF(qBound(-m_zeroShift, y, 1. - m_zeroShift)); + changeColor(m_color); + + } +} + +void WheelContainer::mousePressEvent(QMouseEvent *event) { if (event->modifiers() & Qt::ShiftModifier) { QPoint clicked = event->pos(); if (m_wheelRegion.contains(clicked)) { QPointF current = pointForColor(); QPointF diff = clicked - current; double factor = fabs(diff.x()) > fabs(diff.y()) ? fabs(diff.x()) : fabs(diff.y()); diff /= factor; m_lastPoint = current + diff; } else if (m_sliderRegion.contains(clicked)) { double y = yForColor(); int offset = clicked.y() > y ? 1 : -1; m_lastPoint = QPointF(clicked.x(), y + offset); } else { return; } - } else { m_lastPoint = event->pos(); } if (m_wheelRegion.contains(m_lastPoint.toPoint())) { m_isInWheel = true; m_isInSquare = false; if (event->button() == Qt::LeftButton) { changeColor(colorForPoint(m_lastPoint)); } else { // reset to default on middle/right button qreal r = m_color.redF(); qreal b = m_color.blueF(); qreal g = m_color.greenF(); qreal max = qMax(r, b); max = qMax(max, g); changeColor(NegQColor::fromRgbF(max, max, max)); } } else if (m_sliderRegion.contains(m_lastPoint.toPoint())) { m_isInWheel = false; m_isInSquare = true; if (event->button() == Qt::LeftButton) { changeColor(colorForPoint(m_lastPoint)); } else { NegQColor c; c = NegQColor::fromHsvF(m_color.hueF(), m_color.saturationF(), m_defaultValue / m_sizeFactor); changeColor(c); } } m_isMouseDown = true; } -void ColorWheel::mouseMoveEvent(QMouseEvent *event) +void WheelContainer::mouseMoveEvent(QMouseEvent *event) { if (!m_isMouseDown) { return; } if (event->modifiers() & Qt::ShiftModifier) { if (m_isInWheel) { QPointF diff = event->pos() - m_lastPoint; double factor = fabs(diff.x()) > fabs(diff.y()) ? fabs(diff.x()) : fabs(diff.y()); diff /= factor; m_lastPoint += diff; } else if (m_isInSquare) { double y = yForColor(); int offset = event->pos().y() > y ? 1 : -1; m_lastPoint = QPointF(event->pos().x(), y + offset); } else { return; } } else { m_lastPoint = event->pos(); } if (m_wheelRegion.contains(m_lastPoint.toPoint()) && m_isInWheel) { const NegQColor color = colorForPoint(m_lastPoint); changeColor(color); } else if (m_sliderRegion.contains(m_lastPoint.toPoint()) && m_isInSquare) { const NegQColor color = colorForPoint(m_lastPoint); changeColor(color); } } -void ColorWheel::mouseReleaseEvent(QMouseEvent *event) +void WheelContainer::mouseReleaseEvent(QMouseEvent *event) { Q_UNUSED(event) m_isMouseDown = false; m_isInWheel = false; m_isInSquare = false; } -void ColorWheel::resizeEvent(QResizeEvent *event) +void WheelContainer::resizeEvent(QResizeEvent *event) { m_image = QImage(event->size(), QImage::Format_ARGB32_Premultiplied); m_image.fill(palette().window().color().rgb()); drawWheel(); drawSlider(); update(); } -QString ColorWheel::getParamValues() +const QString WheelContainer::getParamValues() const +{ + return QString::number(m_color.redF() * m_sizeFactor, 'g', 3) + QLatin1Char(',') + QString::number(m_color.greenF() * m_sizeFactor, 'g', 3) + + QLatin1Char(',') + QString::number(m_color.blueF() * m_sizeFactor, 'g', 3); +} + +const QList WheelContainer::getNiceParamValues() const { - return QString::number(m_color.redF() * m_sizeFactor, 'g', 2) + QLatin1Char(',') + QString::number(m_color.greenF() * m_sizeFactor, 'g', 2) + - QLatin1Char(',') + QString::number(m_color.blueF() * m_sizeFactor, 'g', 2); + return {m_color.redF()* m_sizeFactor, m_color.greenF()* m_sizeFactor , m_color.blueF()* m_sizeFactor}; } -void ColorWheel::paintEvent(QPaintEvent *event) +void WheelContainer::paintEvent(QPaintEvent *event) { Q_UNUSED(event) QPainter painter(this); // QStyleOption opt; // opt.init(this); painter.setRenderHint(QPainter::Antialiasing); painter.drawImage(0, 0, m_image); // painter.drawRect(0, 0, width(), height()); - painter.drawText(m_margin, wheelSize() + m_unitSize - m_margin, m_name + QLatin1Char(' ') + getParamValues()); + //painter.drawText(m_margin, wheelSize() + m_unitSize - m_margin, m_name + QLatin1Char(' ') + getParamValues()); drawWheelDot(painter); drawSliderBar(painter); // style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this); } -void ColorWheel::drawWheel() +void WheelContainer::drawWheel() { int r = wheelSize(); QPainter painter(&m_image); painter.setRenderHint(QPainter::Antialiasing); m_image.fill(0); // transparent QConicalGradient conicalGradient; conicalGradient.setColorAt(0.0, Qt::red); conicalGradient.setColorAt(60.0 / 360.0, Qt::yellow); conicalGradient.setColorAt(135.0 / 360.0, Qt::green); conicalGradient.setColorAt(180.0 / 360.0, Qt::cyan); conicalGradient.setColorAt(240.0 / 360.0, Qt::blue); conicalGradient.setColorAt(315.0 / 360.0, Qt::magenta); conicalGradient.setColorAt(1.0, Qt::red); QRadialGradient radialGradient(0.0, 0.0, r / 2); radialGradient.setColorAt(0.0, Qt::white); radialGradient.setColorAt(1.0, Qt::transparent); painter.translate(r / 2, r / 2); painter.rotate(-105); QBrush hueBrush(conicalGradient); painter.setPen(Qt::NoPen); painter.setBrush(hueBrush); - painter.drawEllipse(QPoint(0, 0), r / 2 - m_margin, r / 2 - m_margin); + painter.drawEllipse(QPointF(0, 0), r / 2 - m_margin, r / 2 - m_margin); QBrush saturationBrush(radialGradient); painter.setBrush(saturationBrush); - painter.drawEllipse(QPoint(0, 0), r / 2 - m_margin, r / 2 - m_margin); + painter.drawEllipse(QPointF(0, 0), r / 2 - m_margin, r / 2 - m_margin); + + painter.setBrush(Qt::gray); + painter.setOpacity(0.4); + painter.drawEllipse(QPointF(0, 0), r / 2 - m_unitSize * .6, r / 2 - m_unitSize * .6); m_wheelRegion = QRegion(r / 2, r / 2, r - 2 * m_margin, r - 2 * m_margin, QRegion::Ellipse); m_wheelRegion.translate(-(r - 2 * m_margin) / 2, -(r - 2 * m_margin) / 2); } -void ColorWheel::drawSlider() +void WheelContainer::drawSlider() { QPainter painter(&m_image); painter.setRenderHint(QPainter::Antialiasing); - int ws = wheelSize(); + int ws = wheelSize() + m_unitSize * .2; qreal scale = qreal(ws + m_sliderWidth) / maximumWidth(); - int w = m_sliderWidth * scale; + int w = m_sliderWidth * scale - m_unitSize * .4; int h = ws - m_margin * 2; QLinearGradient gradient(0, 0, w, h); gradient.setColorAt(0.0, Qt::white); gradient.setColorAt(1.0, Qt::black); QBrush brush(gradient); painter.setPen(Qt::NoPen); painter.setBrush(brush); painter.translate(ws, m_margin); painter.drawRect(0, 0, w, h); m_sliderRegion = QRegion(ws, m_margin, w, h); } -void ColorWheel::drawWheelDot(QPainter &painter) +void WheelContainer::drawWheelDot(QPainter &painter) { int r = wheelSize() / 2; QPen pen(Qt::white); pen.setWidth(2); painter.setPen(pen); painter.setBrush(Qt::black); painter.translate(r, r); painter.rotate(360.0 - m_color.hue()); painter.rotate(-105); // r -= margin; painter.drawEllipse(QPointF(m_color.saturationF() * r, 0.0), 4, 4); painter.resetTransform(); } -QPointF ColorWheel::pointForColor() +QPointF WheelContainer::pointForColor() { int r = wheelSize() / 2; QTransform transform; transform.translate(r, r); transform.rotate(255 - m_color.hue()); transform.translate(m_color.saturationF() * r, 0); return transform.map(QPointF(0, 0)); } -double ColorWheel::yForColor() +double WheelContainer::yForColor() { qreal value = 1.0 - m_color.valueF(); if (m_id == QLatin1String("lift")) { value -= m_zeroShift; } int ws = wheelSize(); int h = ws - m_margin * 2; return m_margin + value * h; } -void ColorWheel::drawSliderBar(QPainter &painter) +void WheelContainer::drawSliderBar(QPainter &painter) { qreal value = 1.0 - m_color.valueF(); if (m_id == QLatin1String("lift")) { value -= m_zeroShift; } int ws = wheelSize(); qreal scale = qreal(ws + m_sliderWidth) / maximumWidth(); int w = m_sliderWidth * scale; int h = ws - m_margin * 2; QPen pen(Qt::white); pen.setWidth(2); painter.setPen(pen); painter.setBrush(Qt::black); painter.translate(ws, m_margin + value * h); painter.drawRect(0, 0, w, 4); painter.resetTransform(); } -void ColorWheel::changeColor(const NegQColor &color) +void WheelContainer::changeColor(const NegQColor &color) { m_color = color; drawWheel(); drawSlider(); update(); emit colorChange(m_color); } + + +ColorWheel::ColorWheel(QString id, QString name, NegQColor color, QWidget *parent) + : QWidget(parent) +{ + QFontInfo info(font()); + int unitSize = info.pixelSize(); + QVBoxLayout *lay = new QVBoxLayout(this); + m_wheelName = new QLabel(name, this); + m_wheelName->setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont)); + lay->addWidget(m_wheelName); + m_container = new WheelContainer(id, name, color, unitSize, this); + QHBoxLayout *hb = new QHBoxLayout; + m_redEdit = new QDoubleSpinBox(this); + m_redEdit->setPrefix(i18n("R: ")); + m_redEdit->setFrame(QFrame::NoFrame); + m_redEdit->setDecimals(3); + m_redEdit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + m_redEdit->setFont(m_wheelName->font()); + m_redEdit->setObjectName(QStringLiteral("dragMinimal")); + m_greenEdit = new QDoubleSpinBox(this); + m_greenEdit->setPrefix(i18n("G: ")); + m_greenEdit->setObjectName(QStringLiteral("dragMinimal")); + m_greenEdit->setFont(m_wheelName->font()); + m_greenEdit->setDecimals(3); + m_greenEdit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + m_blueEdit = new QDoubleSpinBox(this); + m_blueEdit->setPrefix(i18n("B: ")); + m_blueEdit->setObjectName(QStringLiteral("dragMinimal")); + m_blueEdit->setFont(m_wheelName->font()); + m_blueEdit->setDecimals(3); + m_blueEdit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + lay->setContentsMargins(0, 0, 2, 0); + lay->setSpacing(0); + lay->addWidget(m_container); + hb->addWidget(m_redEdit); + hb->addWidget(m_greenEdit); + hb->addWidget(m_blueEdit); + hb->setSpacing(0); + hb->setContentsMargins(0, 0, 0, 0); + lay->addLayout(hb); + m_container->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + connect(m_container, &WheelContainer::colorChange, [&] (const NegQColor &col) { + QList vals = m_container->getNiceParamValues(); + m_redEdit->blockSignals(true); + m_greenEdit->blockSignals(true); + m_blueEdit->blockSignals(true); + m_redEdit->setValue(vals.at(0)); + m_greenEdit->setValue(vals.at(1)); + m_blueEdit->setValue(vals.at(2)); + m_redEdit->blockSignals(false); + m_greenEdit->blockSignals(false); + m_blueEdit->blockSignals(false); + emit colorChange(col); + }); + connect(m_redEdit, static_cast(&QDoubleSpinBox::valueChanged), [&]() { + m_container->setRedColor(m_redEdit->value()); + }); + connect(m_greenEdit, static_cast(&QDoubleSpinBox::valueChanged), [&]() { + m_container->setGreenColor(m_greenEdit->value()); + }); + connect(m_blueEdit, static_cast(&QDoubleSpinBox::valueChanged), [&]() { + m_container->setBlueColor(m_blueEdit->value()); + }); + setMinimumHeight(m_wheelName->height() + m_container->minimumHeight() + m_redEdit->height()); + setMaximumWidth(m_container->maximumWidth()); + setMinimumWidth(3 * m_redEdit->sizeHint().width()); +} + + +NegQColor ColorWheel::color() const +{ + return m_container->color(); +} + +void ColorWheel::setColor(QList values) +{ + m_container->setColor(values); + QList vals = m_container->getNiceParamValues(); + m_redEdit->blockSignals(true); + m_greenEdit->blockSignals(true); + m_blueEdit->blockSignals(true); + m_redEdit->setValue(values.at(0)); + m_greenEdit->setValue(values.at(1)); + m_blueEdit->setValue(values.at(2)); + m_redEdit->blockSignals(false); + m_greenEdit->blockSignals(false); + m_blueEdit->blockSignals(false); +} + +void ColorWheel::setFactorDefaultZero(qreal factor, qreal defvalue, qreal zero) +{ + m_container->setFactorDefaultZero(factor, defvalue, zero); + if (zero > 0) { + // Lift has a special range + m_redEdit->setRange(-1, 1); + m_greenEdit->setRange(-1, 1); + m_blueEdit->setRange(-1, 1); + } else { + m_redEdit->setRange(0, factor); + m_greenEdit->setRange(0, factor); + m_blueEdit->setRange(0, factor); + } + m_redEdit->setSingleStep(.01); + m_greenEdit->setSingleStep(.01); + m_blueEdit->setSingleStep(.01); +} + diff --git a/src/assets/view/widgets/colorwheel.h b/src/assets/view/widgets/colorwheel.h index 190bca26e..85360eea1 100644 --- a/src/assets/view/widgets/colorwheel.h +++ b/src/assets/view/widgets/colorwheel.h @@ -1,100 +1,131 @@ /* * Copyright (c) 2013 Meltytech, LLC * Author: Dan Dennedy * * 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 . */ #ifndef COLORWHEELPARAM_H #define COLORWHEELPARAM_H #include #include #include +class QDoubleSpinBox; +class QLabel; + class NegQColor { public: int8_t sign_r = 1; int8_t sign_g = 1; int8_t sign_b = 1; QColor qcolor; static NegQColor fromHsvF(qreal h, qreal s, qreal l, qreal a = 1.0); static NegQColor fromRgbF(qreal r, qreal g, qreal b, qreal a = 1.0); - qreal redF(); - qreal greenF(); - qreal blueF(); - qreal valueF(); - int hue(); - qreal hueF(); - qreal saturationF(); + qreal redF() const; + qreal greenF() const; + qreal blueF() const; + qreal valueF() const; + int hue() const; + qreal hueF() const; + qreal saturationF() const; + void setRedF(qreal val); + void setGreenF(qreal val); + void setBlueF(qreal val); + void setValueF(qreal val); }; -class ColorWheel : public QWidget +class WheelContainer : public QWidget { Q_OBJECT public: - explicit ColorWheel(QString id, QString name, NegQColor color, QWidget *parent = nullptr); - + explicit WheelContainer(QString id, QString name, NegQColor color, int unitSize, QWidget *parent = nullptr); QSize sizeHint() const override; QSize minimumSizeHint() const override; NegQColor color() const; - void setColor(const NegQColor &color); + void setColor(QList values); void setFactorDefaultZero(qreal factor, qreal defvalue, qreal zero); - -signals: - void colorChange(const NegQColor &color); + const QList getNiceParamValues() const; + void setRedColor(double value); + void setGreenColor(double value); + void setBlueColor(double value); public slots: void changeColor(const NegQColor &color); +signals: + void colorChange(const NegQColor &color); + protected: void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; + void wheelEvent(QWheelEvent *event) override; void resizeEvent(QResizeEvent *event) override; void paintEvent(QPaintEvent *event) override; private: QString m_id; QSize m_initialSize; QImage m_image; bool m_isMouseDown; QPointF m_lastPoint; int m_margin; int m_sliderWidth; QRegion m_wheelRegion; QRegion m_sliderRegion; NegQColor m_color; bool m_isInWheel; bool m_isInSquare; int m_unitSize; QString m_name; qreal m_sizeFactor = 1; qreal m_defaultValue = 1; qreal m_zeroShift = 0; int wheelSize() const; NegQColor colorForPoint(const QPointF &point); QPointF pointForColor(); double yForColor(); void drawWheel(); void drawWheelDot(QPainter &painter); void drawSliderBar(QPainter &painter); void drawSlider(); - QString getParamValues(); + const QString getParamValues() const; +}; + +class ColorWheel : public QWidget +{ + Q_OBJECT +public: + explicit ColorWheel(QString id, QString name, NegQColor color, QWidget *parent = nullptr); + NegQColor color() const; + void setColor(QList values); + void setFactorDefaultZero(qreal factor, qreal defvalue, qreal zero); + +private: + WheelContainer *m_container; + QLabel *m_wheelName; + QDoubleSpinBox *m_redEdit; + QDoubleSpinBox *m_greenEdit; + QDoubleSpinBox *m_blueEdit; + +signals: + void colorChange(const NegQColor &color); }; #endif // COLORWHEEL_H diff --git a/src/assets/view/widgets/lumaliftgainparam.cpp b/src/assets/view/widgets/lumaliftgainparam.cpp index 367a7b1e0..32bff477a 100644 --- a/src/assets/view/widgets/lumaliftgainparam.cpp +++ b/src/assets/view/widgets/lumaliftgainparam.cpp @@ -1,140 +1,132 @@ /*************************************************************************** * Copyright (C) 2018 by Jean-Baptiste Mardelle (jb@kdenlive.org) * * Some code was borrowed from shotcut * * * * 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 2 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ #include "lumaliftgainparam.hpp" #include "assets/model/assetparametermodel.hpp" #include "colorwheel.h" #include "utils/flowlayout.h" #include static const double LIFT_FACTOR = 2.0; static const double GAMMA_FACTOR = 2.0; static const double GAIN_FACTOR = 4.0; LumaLiftGainParam::LumaLiftGainParam(std::shared_ptr model, QModelIndex index, QWidget *parent) : AbstractParamWidget(std::move(model), index, parent) { m_flowLayout = new FlowLayout(this, 2, 2, 2); setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); m_locale.setNumberOptions(QLocale::OmitGroupSeparator); m_lift = new ColorWheel(QStringLiteral("lift"), i18n("Lift"), NegQColor(), this); m_lift->setFactorDefaultZero(LIFT_FACTOR, 0, 0.5); connect(m_lift, &ColorWheel::colorChange, this, &LumaLiftGainParam::liftChanged); m_gamma = new ColorWheel(QStringLiteral("gamma"), i18n("Gamma"), NegQColor(), this); m_gamma->setFactorDefaultZero(GAMMA_FACTOR, 1, 0); connect(m_gamma, &ColorWheel::colorChange, this, &LumaLiftGainParam::gammaChanged); m_gain = new ColorWheel(QStringLiteral("gain"), i18n("Gain"), NegQColor(), this); m_gain->setFactorDefaultZero(GAIN_FACTOR, 1, 0); connect(m_gain, &ColorWheel::colorChange, this, &LumaLiftGainParam::gainChanged); QMap indexes; for (int i = 0; i < m_model->rowCount(); ++i) { QModelIndex local_index = m_model->index(i, 0); QString name = m_model->data(local_index, AssetParameterModel::NameRole).toString(); indexes.insert(name, local_index); } m_flowLayout->addWidget(m_lift); m_flowLayout->addWidget(m_gamma); m_flowLayout->addWidget(m_gain); setLayout(m_flowLayout); slotRefresh(); connect(this, &LumaLiftGainParam::liftChanged, [this, indexes]() { NegQColor liftColor = m_lift->color(); QList ixes{indexes.value(QStringLiteral("lift_r")),indexes.value(QStringLiteral("lift_g")), indexes.value(QStringLiteral("lift_b"))}; QStringList values {m_locale.toString(liftColor.redF()), m_locale.toString(liftColor.greenF()), m_locale.toString(liftColor.blueF())}; emit valuesChanged(ixes, values, true); }); connect(this, &LumaLiftGainParam::gammaChanged, [this, indexes]() { NegQColor gammaColor = m_gamma->color(); QList ixes{indexes.value(QStringLiteral("gamma_r")),indexes.value(QStringLiteral("gamma_g")), indexes.value(QStringLiteral("gamma_b"))}; QStringList values {m_locale.toString(gammaColor.redF() * GAMMA_FACTOR), m_locale.toString(gammaColor.greenF() * GAMMA_FACTOR), m_locale.toString(gammaColor.blueF() * GAMMA_FACTOR)}; emit valuesChanged(ixes, values, true); }); connect(this, &LumaLiftGainParam::gainChanged, [this, indexes]() { NegQColor gainColor = m_gain->color(); QList ixes{indexes.value(QStringLiteral("gain_r")),indexes.value(QStringLiteral("gain_g")), indexes.value(QStringLiteral("gain_b"))}; QStringList values {m_locale.toString(gainColor.redF() * GAIN_FACTOR), m_locale.toString(gainColor.greenF() * GAIN_FACTOR), m_locale.toString(gainColor.blueF() * GAIN_FACTOR)}; emit valuesChanged(ixes, values, true); }); } void LumaLiftGainParam::updateEffect(QDomElement &effect) { NegQColor lift = m_lift->color(); NegQColor gamma = m_gamma->color(); NegQColor gain = m_gain->color(); QMap values; values.insert(QStringLiteral("lift_r"), lift.redF() * LIFT_FACTOR); values.insert(QStringLiteral("lift_g"), lift.greenF() * LIFT_FACTOR); values.insert(QStringLiteral("lift_b"), lift.blueF() * LIFT_FACTOR); values.insert(QStringLiteral("gamma_r"), gamma.redF() * GAMMA_FACTOR); values.insert(QStringLiteral("gamma_g"), gamma.greenF() * GAMMA_FACTOR); values.insert(QStringLiteral("gamma_b"), gamma.blueF() * GAMMA_FACTOR); values.insert(QStringLiteral("gain_r"), gain.redF() * GAIN_FACTOR); values.insert(QStringLiteral("gain_g"), gain.greenF() * GAIN_FACTOR); values.insert(QStringLiteral("gain_b"), gain.blueF() * GAIN_FACTOR); QDomNodeList namenode = effect.childNodes(); for (int i = 0; i < namenode.count(); ++i) { QDomElement pa = namenode.item(i).toElement(); if (pa.tagName() != QLatin1String("parameter")) { continue; } if (values.contains(pa.attribute(QStringLiteral("name")))) { pa.setAttribute(QStringLiteral("value"), (int)(values.value(pa.attribute(QStringLiteral("name"))) * m_locale.toDouble(pa.attribute(QStringLiteral("factor"), QStringLiteral("1"))))); } } } void LumaLiftGainParam::resizeEvent(QResizeEvent *ev) { setFixedHeight(m_flowLayout->miniHeight()); QWidget::resizeEvent(ev); emit updateHeight(); } void LumaLiftGainParam::slotShowComment(bool) {} void LumaLiftGainParam::slotRefresh() { QMap values; for (int i = 0; i < m_model->rowCount(); ++i) { QModelIndex local_index = m_model->index(i, 0); QString name = m_model->data(local_index, AssetParameterModel::NameRole).toString(); double val = m_locale.toDouble(m_model->data(local_index, AssetParameterModel::ValueRole).toString()); values.insert(name, val); } - - NegQColor lift = NegQColor::fromRgbF(values.value(QStringLiteral("lift_r")) / LIFT_FACTOR, values.value(QStringLiteral("lift_g")) / LIFT_FACTOR, - values.value(QStringLiteral("lift_b")) / LIFT_FACTOR); - NegQColor gamma = NegQColor::fromRgbF(values.value(QStringLiteral("gamma_r")) / GAMMA_FACTOR, values.value(QStringLiteral("gamma_g")) / GAMMA_FACTOR, - values.value(QStringLiteral("gamma_b")) / GAMMA_FACTOR); - NegQColor gain = NegQColor::fromRgbF(values.value(QStringLiteral("gain_r")) / GAIN_FACTOR, values.value(QStringLiteral("gain_g")) / GAIN_FACTOR, - values.value(QStringLiteral("gain_b")) / GAIN_FACTOR); - - m_lift->setColor(lift); - m_gamma->setColor(gamma); - m_gain->setColor(gain); + m_lift->setColor({values.value(QStringLiteral("lift_r")), values.value(QStringLiteral("lift_g")), values.value(QStringLiteral("lift_b"))}); + m_gamma->setColor({values.value(QStringLiteral("gamma_r")), values.value(QStringLiteral("gamma_g")), values.value(QStringLiteral("gamma_b"))}); + m_gain->setColor({values.value(QStringLiteral("gain_r")), values.value(QStringLiteral("gain_g")), values.value(QStringLiteral("gain_b"))}); }