diff --git a/src/assets/view/widgets/curves/curveparamwidget.ipp b/src/assets/view/widgets/curves/curveparamwidget.ipp index c3c24f8e5..224fe9a81 100644 --- a/src/assets/view/widgets/curves/curveparamwidget.ipp +++ b/src/assets/view/widgets/curves/curveparamwidget.ipp @@ -1,434 +1,434 @@ /*************************************************************************** * Copyright (C) 2016 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 "bezier/beziersplineeditor.h" #include "colortools.h" #include "cubic/kis_curve_widget.h" #include "kdenlivesettings.h" #include "widgets/dragvalue.h" #include /*@brief this label is a pixmap corresponding to a legend of the axis*/ template class ValueLabel : public QLabel { public: /**@brief Creates the widget @param isVert This parameter is true if the widget is vertical @param mode This is the original mode @param parent Parent of the widget */ ValueLabel(bool isVert, typename CurveParamWidget::CurveModes mode, QWidget *parent) : QLabel(parent) , m_mode(mode) , m_isVert(isVert) { if (m_isVert) { setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); setFixedWidth(10); } else { setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); setFixedHeight(10); } setScaledContents(true); } public slots: void setMode(typename CurveParamWidget::CurveModes m) { m_mode = m; createPixmap(); } private: using CurveModes = typename CurveParamWidget::CurveModes; void createPixmap() { QTransform t; QSize s = size(); if (!m_isVert) { t.rotate(90); s.setHeight(size().width()); s.setWidth(size().height()); } if (m_mode == CurveModes::Hue) { setPixmap(QPixmap::fromImage(ColorTools::hsvCurvePlane(s, QColor::fromHsv(200, 200, 200), ColorTools::COM_H, ColorTools::COM_H)).transformed(t)); } else if (m_mode == CurveModes::Saturation) { setPixmap(QPixmap()); } else { auto color = CurveParamWidget::modeToColorsRGB(m_mode); setPixmap(QPixmap::fromImage(ColorTools::rgbCurveLine(s, color, palette().background().color().rgb())).transformed(t)); } } typename CurveParamWidget::CurveModes m_mode; bool m_isVert; }; template <> void CurveParamWidget::slotUpdatePointP(double, bool final) { m_edit->updateCurrentPoint(QPointF(m_pX->value(), m_pY->value()), final); } template <> void CurveParamWidget::slotUpdatePointP(double, bool final) { BPoint p = m_edit->getCurrentPoint(); p.setP(QPointF(m_pX->value(), m_pY->value())); m_edit->updateCurrentPoint(p, final); } template <> void CurveParamWidget::slotUpdatePointH1(double /*value*/, bool final) { BPoint p = m_edit->getCurrentPoint(); p.setH1(QPointF(m_h1X->value(), m_h1Y->value())); m_edit->updateCurrentPoint(p, final); } template void CurveParamWidget::slotUpdatePointH1(double /*value*/, bool /*final*/) {} template <> void CurveParamWidget::slotUpdatePointH2(double /*value*/, bool final) { BPoint p = m_edit->getCurrentPoint(); p.setH2(QPointF(m_h2X->value(), m_h2Y->value())); m_edit->updateCurrentPoint(p, final); } template void CurveParamWidget::slotUpdatePointH2(double /*value*/, bool /*final*/) {} template <> void CurveParamWidget::slotSetHandlesLinked(bool linked) { BPoint p = m_edit->getCurrentPoint(); p.setHandlesLinked(linked); m_edit->updateCurrentPoint(p); } template void CurveParamWidget::slotSetHandlesLinked(bool /*linked*/) {} template <> void CurveParamWidget::slotShowAllHandles(bool show) { m_edit->setShowAllHandles(show); KdenliveSettings::setBezier_showallhandles(show); } template void CurveParamWidget::slotShowAllHandles(bool /*show*/) {} template CurveParamWidget::CurveParamWidget(std::shared_ptr model, QModelIndex index, QWidget *parent) : AbstractParamWidget(std::move(model), index, parent) , m_mode(CurveModes::Luma) , m_showPixmap(KdenliveSettings::bezier_showpixmap()) { // construct curve editor m_edit = new CurveWidget_t(this); connect(m_edit, static_cast(&CurveWidget_t::currentPoint), this, static_cast::*)(const Point_t &, bool)>(&CurveParamWidget::slotUpdatePointEntries)); // construct and fill layout auto *layout = new QVBoxLayout(this); layout->setSpacing(0); setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); layout->addWidget(m_edit); m_leftParam = new ValueLabel(true, m_mode, this); m_leftParam->setFrameStyle(QFrame::StyledPanel | QFrame::Plain); m_leftParam->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_bottomParam = new ValueLabel(false, m_mode, this); m_bottomParam->setFrameStyle(QFrame::StyledPanel | QFrame::Plain); m_bottomParam->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); // horizontal layout to make sure that everything is centered auto *horiz_layout = new QHBoxLayout; horiz_layout->addWidget(m_leftParam); horiz_layout->addWidget(m_bottomParam); layout->addLayout(horiz_layout); auto *widget = new QWidget(this); widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); m_ui.setupUi(widget); layout->addWidget(widget); // set up icons and initial button states m_ui.buttonLinkHandles->setIcon(QIcon::fromTheme(QStringLiteral("edit-link"))); m_ui.buttonDeletePoint->setIcon(QIcon::fromTheme(QStringLiteral("list-remove"))); m_ui.buttonZoomIn->setIcon(QIcon::fromTheme(QStringLiteral("zoom-in"))); m_ui.buttonZoomOut->setIcon(QIcon::fromTheme(QStringLiteral("zoom-out"))); m_ui.buttonGridChange->setIcon(QIcon::fromTheme(QStringLiteral("view-grid"))); m_ui.buttonShowPixmap->setIcon(QIcon(QPixmap::fromImage(ColorTools::rgbCurvePlane(QSize(16, 16), ColorTools::ColorsRGB::Luma, (float)0.8)))); m_ui.buttonResetSpline->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); m_ui.buttonShowAllHandles->setIcon(QIcon::fromTheme(QStringLiteral("draw-bezier-curves"))); m_ui.widgetPoint->setEnabled(false); m_edit->setGridLines(KdenliveSettings::bezier_gridlines()); m_ui.buttonShowPixmap->setChecked(KdenliveSettings::bezier_showpixmap()); m_ui.buttonShowAllHandles->setChecked(KdenliveSettings::bezier_showallhandles()); slotShowAllHandles(KdenliveSettings::bezier_showallhandles()); // connect buttons to their slots connect(m_ui.buttonLinkHandles, &QAbstractButton::toggled, this, &CurveParamWidget::slotSetHandlesLinked); connect(m_ui.buttonDeletePoint, &QAbstractButton::clicked, m_edit, &CurveWidget_t::slotDeleteCurrentPoint); connect(m_ui.buttonZoomIn, &QAbstractButton::clicked, m_edit, &CurveWidget_t::slotZoomIn); connect(m_ui.buttonZoomOut, &QAbstractButton::clicked, m_edit, &CurveWidget_t::slotZoomOut); connect(m_ui.buttonGridChange, &QAbstractButton::clicked, this, &CurveParamWidget::slotGridChange); connect(m_ui.buttonShowPixmap, &QAbstractButton::toggled, this, &CurveParamWidget::slotShowPixmap); connect(m_ui.buttonResetSpline, &QAbstractButton::clicked, m_edit, &CurveWidget_t::reset); connect(m_ui.buttonShowAllHandles, &QAbstractButton::toggled, this, &CurveParamWidget::slotShowAllHandles); setupLayoutPoint(); setupLayoutHandles(); slotRefresh(); deleteIrrelevantItems(); // emit the signal of the base class when appropriate connect(m_edit, &CurveWidget_t::modified, [this]() { emit valueChanged(m_index, m_edit->toString(), true); }); } template <> void CurveParamWidget::deleteIrrelevantItems() { m_ui.gridLayout->removeWidget(m_ui.buttonShowAllHandles); delete m_ui.buttonShowAllHandles; } template void CurveParamWidget::deleteIrrelevantItems() { // Nothing to do in general } template void CurveParamWidget::setupLayoutPoint() { - m_pX = new DragValue(i18n("In"), 0, 3, 0, 1, -1, QString(), false, this); + m_pX = new DragValue(i18n("In"), 0, 3, 0, 1, -1, QString(), false, false, this); m_pX->setStep(0.001); - m_pY = new DragValue(i18n("Out"), 0, 3, 0, 1, -1, QString(), false, this); + m_pY = new DragValue(i18n("Out"), 0, 3, 0, 1, -1, QString(), false, false, this); m_pY->setStep(0.001); m_ui.layoutP->addWidget(m_pX); m_ui.layoutP->addWidget(m_pY); connect(m_pX, &DragValue::valueChanged, this, &CurveParamWidget::slotUpdatePointP); connect(m_pY, &DragValue::valueChanged, this, &CurveParamWidget::slotUpdatePointP); } template <> void CurveParamWidget::setupLayoutHandles() { - m_h1X = new DragValue(i18n("X"), 0, 3, -2, 2, -1, QString(), false, this); + m_h1X = new DragValue(i18n("X"), 0, 3, -2, 2, -1, QString(), false, false, this); m_h1X->setStep(0.001); - m_h1Y = new DragValue(i18n("Y"), 0, 3, -2, 2, -1, QString(), false, this); + m_h1Y = new DragValue(i18n("Y"), 0, 3, -2, 2, -1, QString(), false, false, this); m_h1Y->setStep(0.001); - m_h2X = new DragValue(i18n("X"), 0, 3, -2, 2, -1, QString(), false, this); + m_h2X = new DragValue(i18n("X"), 0, 3, -2, 2, -1, QString(), false, false, this); m_h2X->setStep(0.001); - m_h2Y = new DragValue(i18n("Y"), 0, 3, -2, 2, -1, QString(), false, this); + m_h2Y = new DragValue(i18n("Y"), 0, 3, -2, 2, -1, QString(), false, false, this); m_h2Y->setStep(0.001); m_ui.layoutH1->addWidget(new QLabel(i18n("Handle 1:"))); m_ui.layoutH1->addWidget(m_h1X); m_ui.layoutH1->addWidget(m_h1Y); m_ui.layoutH2->addWidget(new QLabel(i18n("Handle 2:"))); m_ui.layoutH2->addWidget(m_h2X); m_ui.layoutH2->addWidget(m_h2Y); connect(m_h1X, &DragValue::valueChanged, this, &CurveParamWidget::slotUpdatePointH1); connect(m_h1Y, &DragValue::valueChanged, this, &CurveParamWidget::slotUpdatePointH1); connect(m_h2X, &DragValue::valueChanged, this, &CurveParamWidget::slotUpdatePointH2); connect(m_h2Y, &DragValue::valueChanged, this, &CurveParamWidget::slotUpdatePointH2); } template void CurveParamWidget::setupLayoutHandles() { // Nothing to do in general } template QString CurveParamWidget::toString() const { return m_edit->toString(); } template void CurveParamWidget::setMode(CurveModes mode) { if (m_mode != mode) { m_mode = mode; if (m_showPixmap) { slotShowPixmap(true); } m_leftParam->setMode(mode); m_bottomParam->setMode(mode); } } template void CurveParamWidget::slotGridChange() { m_edit->setGridLines((m_edit->gridLines() + 1) % 9); KdenliveSettings::setBezier_gridlines(m_edit->gridLines()); } template ColorTools::ColorsRGB CurveParamWidget::modeToColorsRGB(CurveModes mode) { switch (mode) { case CurveModes::Red: return ColorTools::ColorsRGB::R; case CurveModes::Green: return ColorTools::ColorsRGB::G; case CurveModes::Blue: return ColorTools::ColorsRGB::B; case CurveModes::Luma: return ColorTools::ColorsRGB::Luma; case CurveModes::Alpha: return ColorTools::ColorsRGB::A; case CurveModes::RGB: case CurveModes::Hue: case CurveModes::Saturation: default: return ColorTools::ColorsRGB::RGB; } return ColorTools::ColorsRGB::RGB; } template void CurveParamWidget::slotShowPixmap(bool show) { m_showPixmap = show; KdenliveSettings::setBezier_showpixmap(show); if (show) { if (m_mode == CurveModes::Hue) { m_edit->setPixmap( QPixmap::fromImage(ColorTools::hsvCurvePlane(m_edit->size(), QColor::fromHsv(200, 200, 200), ColorTools::COM_H, ColorTools::COM_H))); } else if (m_mode == CurveModes::Saturation) { m_edit->setPixmap(QPixmap()); } else { auto color = modeToColorsRGB(m_mode); m_edit->setPixmap(QPixmap::fromImage(ColorTools::rgbCurvePlane(m_edit->size(), color, 1, palette().window().color().rgb()))); } } else { m_edit->setPixmap(QPixmap()); } } template <> void CurveParamWidget::slotUpdatePointEntries(const BPoint &p, bool extremal) { blockSignals(true); if (p == BPoint()) { m_ui.widgetPoint->setEnabled(false); } else { m_ui.widgetPoint->setEnabled(true); // disable irrelevant buttons if the point is extremal m_pX->setEnabled(!extremal); m_ui.buttonDeletePoint->setEnabled(!extremal); m_ui.buttonLinkHandles->setEnabled(!extremal); if (extremal && p.p.x() + 1e-4 >= 1.00) { // last point m_h2X->setEnabled(false); m_h2Y->setEnabled(false); } else { m_h2X->setEnabled(true); m_h2Y->setEnabled(true); } if (extremal && p.p.x() <= 0.01) { // first point m_h1X->setEnabled(false); m_h1Y->setEnabled(false); } else { m_h1X->setEnabled(true); m_h1Y->setEnabled(true); } for (auto elem : {m_pX, m_pY, m_h1X, m_h1Y, m_h2X, m_h2Y}) { elem->blockSignals(true); } m_pX->setValue(p.p.x()); m_pY->setValue(p.p.y()); m_h1X->setValue(p.h1.x()); m_h1Y->setValue(p.h1.y()); m_h2X->setValue(p.h2.x()); m_h2Y->setValue(p.h2.y()); for (auto elem : {m_pX, m_pY, m_h1X, m_h1Y, m_h2X, m_h2Y}) { elem->blockSignals(false); } m_ui.buttonLinkHandles->setChecked(p.handlesLinked); } blockSignals(false); } template void CurveParamWidget::slotUpdatePointEntries(const BPoint &p, bool extremal) { Q_UNUSED(p); Q_UNUSED(extremal); // Wrong slot called in curve widget Q_ASSERT(false); } template <> void CurveParamWidget::slotUpdatePointEntries(const QPointF &p, bool extremal) { blockSignals(true); if (p == QPointF()) { m_ui.widgetPoint->setEnabled(false); } else { m_ui.widgetPoint->setEnabled(true); // disable irrelevant buttons if the point is extremal m_pX->setEnabled(!extremal); m_ui.buttonDeletePoint->setEnabled(!extremal); for (auto elem : {m_pX, m_pY}) { elem->blockSignals(true); } m_pX->setValue(p.x()); m_pY->setValue(p.y()); for (auto elem : {m_pX, m_pY}) { elem->blockSignals(false); } } blockSignals(false); } template void CurveParamWidget::slotUpdatePointEntries(const QPointF &p, bool extremal) { Q_UNUSED(p); Q_UNUSED(extremal); // Wrong slot called in curve widget Q_ASSERT(false); } template void CurveParamWidget::slotShowComment(bool show) { Q_UNUSED(show); } template void CurveParamWidget::slotRefresh() { if (m_model->data(m_index, AssetParameterModel::TypeRole).template value() == ParamType::Curve) { QList points; QLocale locale; // Rounding gives really weird results. (int) (10 * 0.3) gives 2! So for now, add 0.5 to get correct result int number = m_model->data(m_index, AssetParameterModel::Enum3Role).toDouble() * 10 + 0.5; int start = m_model->data(m_index, AssetParameterModel::MinRole).toInt(); // for the curve, inpoints are numbered: 6, 8, 10, 12, 14 // outpoints, 7, 9, 11, 13,15 so we need to deduce these enums int inRef = (int)AssetParameterModel::Enum6Role + 2 * (start - 1); int outRef = (int)AssetParameterModel::Enum7Role + 2 * (start - 1); for (int j = start; j <= number; ++j) { double inVal = m_model->data(m_index, (AssetParameterModel::DataRoles)inRef).toDouble(); double outVal = m_model->data(m_index, (AssetParameterModel::DataRoles)outRef).toDouble(); points << QPointF(inVal, outVal); inRef += 2; outRef += 2; } if (!points.isEmpty()) { m_edit->setFromString(KisCubicCurve(points).toString()); } } else { m_edit->setFromString(m_model->data(m_index, AssetParameterModel::ValueRole).toString()); } } template void CurveParamWidget::setMaxPoints(int max) { m_edit->setMaxPoints(max); } template void CurveParamWidget::resizeEvent(QResizeEvent *e) { QWidget::resizeEvent(e); emit updateHeight(); }