Warning, /multimedia/kdenlive/src/assets/view/widgets/curves/curveparamwidget.ipp is written in an unsupported language. File is not indexed.
0001 /*
0002 * SPDX-FileCopyrightText: 2016 Nicolas Carion
0003 * SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005
0006 #include "bezier/beziersplineeditor.h"
0007 #include "utils/colortools.h"
0008 #include "cubic/kis_curve_widget.h"
0009 #include "kdenlivesettings.h"
0010 #include "widgets/dragvalue.h"
0011 #include <KLocalizedString>
0012
0013 /** @brief this label is a pixmap corresponding to a legend of the axis*/
0014 template <typename CurveWidget_t> class ValueLabel : public QLabel
0015 {
0016 public:
0017 /** @brief Creates the widget
0018 @param isVert This parameter is true if the widget is vertical
0019 @param mode This is the original mode
0020 @param parent Parent of the widget
0021 */
0022 ValueLabel(bool isVert, typename CurveParamWidget<CurveWidget_t>::CurveModes mode, QWidget *parent)
0023 : QLabel(parent)
0024 , m_mode(mode)
0025 , m_isVert(isVert)
0026 {
0027 if (m_isVert) {
0028 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
0029 setFixedWidth(10);
0030 } else {
0031 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
0032 setFixedHeight(10);
0033 }
0034 setScaledContents(true);
0035 }
0036
0037 public Q_SLOTS:
0038 void setMode(typename CurveParamWidget<CurveWidget_t>::CurveModes m)
0039 {
0040 m_mode = m;
0041 createPixmap();
0042 }
0043
0044 private:
0045 using CurveModes = typename CurveParamWidget<CurveWidget_t>::CurveModes;
0046 void createPixmap()
0047 {
0048 QTransform t;
0049 QSize s = size();
0050 if (!m_isVert) {
0051 t.rotate(90);
0052 s.setHeight(size().width());
0053 s.setWidth(size().height());
0054 }
0055 if (m_mode == CurveModes::Hue) {
0056 setPixmap(QPixmap::fromImage(ColorTools::hsvCurvePlane(s, QColor::fromHsv(200, 200, 200), ColorTools::COM_H, ColorTools::COM_H)).transformed(t));
0057 } else if (m_mode == CurveModes::Saturation) {
0058 setPixmap(QPixmap());
0059 } else {
0060 auto color = CurveParamWidget<CurveWidget_t>::modeToColorsRGB(m_mode);
0061 setPixmap(QPixmap::fromImage(ColorTools::rgbCurveLine(s, color, palette().window().color().rgb())).transformed(t));
0062 }
0063 }
0064
0065 typename CurveParamWidget<CurveWidget_t>::CurveModes m_mode;
0066 bool m_isVert;
0067 };
0068
0069 template <> void CurveParamWidget<KisCurveWidget>::slotUpdatePointP(double, bool final)
0070 {
0071 m_edit->updateCurrentPoint(QPointF(m_pX->value(), m_pY->value()), final);
0072 }
0073
0074 template <> void CurveParamWidget<BezierSplineEditor>::slotUpdatePointP(double, bool final)
0075 {
0076 BPoint p = m_edit->getCurrentPoint();
0077 p.setP(QPointF(m_pX->value(), m_pY->value()));
0078 m_edit->updateCurrentPoint(p, final);
0079 }
0080
0081 template <> void CurveParamWidget<BezierSplineEditor>::slotUpdatePointH1(double /*value*/, bool final)
0082 {
0083 BPoint p = m_edit->getCurrentPoint();
0084 p.setH1(QPointF(m_h1X->value(), m_h1Y->value()));
0085 m_edit->updateCurrentPoint(p, final);
0086 }
0087 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::slotUpdatePointH1(double /*value*/, bool /*final*/) {}
0088
0089 template <> void CurveParamWidget<BezierSplineEditor>::slotUpdatePointH2(double /*value*/, bool final)
0090 {
0091 BPoint p = m_edit->getCurrentPoint();
0092 p.setH2(QPointF(m_h2X->value(), m_h2Y->value()));
0093 m_edit->updateCurrentPoint(p, final);
0094 }
0095 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::slotUpdatePointH2(double /*value*/, bool /*final*/) {}
0096
0097 template <> void CurveParamWidget<BezierSplineEditor>::slotSetHandlesLinked(bool linked)
0098 {
0099 BPoint p = m_edit->getCurrentPoint();
0100 p.setHandlesLinked(linked);
0101 m_edit->updateCurrentPoint(p);
0102 }
0103 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::slotSetHandlesLinked(bool /*linked*/) {}
0104
0105 template <> void CurveParamWidget<BezierSplineEditor>::slotShowAllHandles(bool show)
0106 {
0107 m_edit->setShowAllHandles(show);
0108 KdenliveSettings::setBezier_showallhandles(show);
0109 }
0110 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::slotShowAllHandles(bool /*show*/) {}
0111 template <typename CurveWidget_t>
0112
0113 CurveParamWidget<CurveWidget_t>::CurveParamWidget(std::shared_ptr<AssetParameterModel> model, QModelIndex index, QWidget *parent)
0114 : AbstractParamWidget(std::move(model), index, parent)
0115 , m_mode(CurveModes::Luma)
0116 , m_showPixmap(KdenliveSettings::bezier_showpixmap())
0117 {
0118 // construct curve editor
0119 m_edit = new CurveWidget_t(this);
0120 connect(m_edit, static_cast<void (CurveWidget_t::*)(const Point_t &, bool)>(&CurveWidget_t::currentPoint), this,
0121 static_cast<void (CurveParamWidget<CurveWidget_t>::*)(const Point_t &, bool)>(&CurveParamWidget<CurveWidget_t>::slotUpdatePointEntries));
0122
0123 // construct and fill layout
0124 auto *layout = new QVBoxLayout(this);
0125 layout->setSpacing(0);
0126 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
0127 layout->addWidget(m_edit);
0128 m_edit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
0129
0130 auto *widget = new QWidget(this);
0131 widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
0132 m_ui.setupUi(widget);
0133 layout->addWidget(widget);
0134
0135 // set up icons and initial button states
0136 m_ui.buttonShowPixmap->setIcon(QIcon(QPixmap::fromImage(ColorTools::rgbCurvePlane(QSize(16, 16), ColorTools::ColorsRGB::Luma, 0.8))));
0137 m_ui.widgetPoint->setEnabled(false);
0138 m_edit->setGridLines(KdenliveSettings::bezier_gridlines());
0139 m_ui.buttonShowPixmap->setChecked(KdenliveSettings::bezier_showpixmap());
0140 m_ui.buttonShowAllHandles->setChecked(KdenliveSettings::bezier_showallhandles());
0141 slotShowAllHandles(KdenliveSettings::bezier_showallhandles());
0142
0143 // connect buttons to their slots
0144 connect(m_ui.buttonLinkHandles, &QAbstractButton::toggled, this, &CurveParamWidget<CurveWidget_t>::slotSetHandlesLinked);
0145 connect(m_ui.buttonDeletePoint, &QAbstractButton::clicked, m_edit, &CurveWidget_t::slotDeleteCurrentPoint);
0146 connect(m_ui.buttonZoomIn, &QAbstractButton::clicked, m_edit, &CurveWidget_t::slotZoomIn);
0147 connect(m_ui.buttonZoomOut, &QAbstractButton::clicked, m_edit, &CurveWidget_t::slotZoomOut);
0148 connect(m_ui.buttonGridChange, &QAbstractButton::clicked, this, &CurveParamWidget<CurveWidget_t>::slotGridChange);
0149 connect(m_ui.buttonShowPixmap, &QAbstractButton::toggled, this, &CurveParamWidget<CurveWidget_t>::slotShowPixmap);
0150 connect(m_ui.buttonResetSpline, &QAbstractButton::clicked, m_edit, &CurveWidget_t::reset);
0151 connect(m_ui.buttonShowAllHandles, &QAbstractButton::toggled, this, &CurveParamWidget<CurveWidget_t>::slotShowAllHandles);
0152
0153 setupLayoutPoint();
0154 setupLayoutHandles();
0155 slotRefresh();
0156
0157 deleteIrrelevantItems();
0158 // emit the signal of the base class when appropriate
0159 connect(m_edit, &CurveWidget_t::modified, [this]() { Q_EMIT valueChanged(m_index, m_edit->toString(), true); });
0160 }
0161
0162 template <> void CurveParamWidget<KisCurveWidget>::deleteIrrelevantItems()
0163 {
0164 delete m_ui.layoutH1;
0165 delete m_ui.layoutH2;
0166 delete m_ui.buttonLinkHandles;
0167 delete m_ui.handlesLayout;
0168 m_ui.gridLayout->removeWidget(m_ui.buttonShowAllHandles);
0169 delete m_ui.buttonShowAllHandles;
0170
0171 }
0172
0173 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::deleteIrrelevantItems()
0174 {
0175 // Nothing to do in general
0176 }
0177
0178 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::setupLayoutPoint()
0179 {
0180 m_pX = new DragValue(i18n("In"), 0, 3, 0, 1, -1, QString(), false, false, this);
0181 m_pX->setStep(0.001);
0182 m_pY = new DragValue(i18n("Out"), 0, 3, 0, 1, -1, QString(), false, false, this);
0183 m_pY->setStep(0.001);
0184 m_ui.layoutP->addWidget(m_pX);
0185 m_ui.layoutP->addWidget(m_pY);
0186 connect(m_pX, &DragValue::valueChanged, this, &CurveParamWidget<CurveWidget_t>::slotUpdatePointP);
0187 connect(m_pY, &DragValue::valueChanged, this, &CurveParamWidget<CurveWidget_t>::slotUpdatePointP);
0188 }
0189
0190 template <> void CurveParamWidget<BezierSplineEditor>::setupLayoutHandles()
0191 {
0192 m_h1X = new DragValue(i18n("X"), 0, 3, -2, 2, -1, QString(), false, false, this);
0193 m_h1X->setStep(0.001);
0194 m_h1Y = new DragValue(i18n("Y"), 0, 3, -2, 2, -1, QString(), false, false, this);
0195 m_h1Y->setStep(0.001);
0196 m_h2X = new DragValue(i18n("X"), 0, 3, -2, 2, -1, QString(), false, false, this);
0197 m_h2X->setStep(0.001);
0198 m_h2Y = new DragValue(i18n("Y"), 0, 3, -2, 2, -1, QString(), false, false, this);
0199 m_h2Y->setStep(0.001);
0200 m_ui.layoutH1->addWidget(new QLabel(i18n("Handle 1:")));
0201 m_ui.layoutH1->addWidget(m_h1X);
0202 m_ui.layoutH1->addWidget(m_h1Y);
0203 m_ui.layoutH2->addWidget(new QLabel(i18n("Handle 2:")));
0204 m_ui.layoutH2->addWidget(m_h2X);
0205 m_ui.layoutH2->addWidget(m_h2Y);
0206 connect(m_h1X, &DragValue::valueChanged, this, &CurveParamWidget<BezierSplineEditor>::slotUpdatePointH1);
0207 connect(m_h1Y, &DragValue::valueChanged, this, &CurveParamWidget<BezierSplineEditor>::slotUpdatePointH1);
0208 connect(m_h2X, &DragValue::valueChanged, this, &CurveParamWidget<BezierSplineEditor>::slotUpdatePointH2);
0209 connect(m_h2Y, &DragValue::valueChanged, this, &CurveParamWidget<BezierSplineEditor>::slotUpdatePointH2);
0210 }
0211
0212 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::setupLayoutHandles()
0213 {
0214 // Nothing to do in general
0215 }
0216
0217 template <typename CurveWidget_t> QString CurveParamWidget<CurveWidget_t>::toString() const
0218 {
0219 return m_edit->toString();
0220 }
0221
0222 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::setMode(CurveModes mode)
0223 {
0224 if (m_mode != mode) {
0225 m_mode = mode;
0226 if (m_showPixmap) {
0227 slotShowPixmap(true);
0228 }
0229 }
0230 }
0231
0232 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::slotGridChange()
0233 {
0234 m_edit->setGridLines((m_edit->gridLines() + 1) % 9);
0235 KdenliveSettings::setBezier_gridlines(m_edit->gridLines());
0236 }
0237
0238 template <typename CurveWidget_t> ColorTools::ColorsRGB CurveParamWidget<CurveWidget_t>::modeToColorsRGB(CurveModes mode)
0239 {
0240 switch (mode) {
0241 case CurveModes::Red:
0242 return ColorTools::ColorsRGB::R;
0243 case CurveModes::Green:
0244 return ColorTools::ColorsRGB::G;
0245 case CurveModes::Blue:
0246 return ColorTools::ColorsRGB::B;
0247 case CurveModes::Luma:
0248 return ColorTools::ColorsRGB::Luma;
0249 case CurveModes::Alpha:
0250 return ColorTools::ColorsRGB::A;
0251 case CurveModes::RGB:
0252 case CurveModes::Hue:
0253 case CurveModes::Saturation:
0254 default:
0255 return ColorTools::ColorsRGB::RGB;
0256 }
0257 return ColorTools::ColorsRGB::RGB;
0258 }
0259 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::slotShowPixmap(bool show)
0260 {
0261 m_showPixmap = show;
0262 KdenliveSettings::setBezier_showpixmap(show);
0263 if (show) {
0264 if (m_mode == CurveModes::Hue) {
0265 m_edit->setPixmap(
0266 QPixmap::fromImage(ColorTools::hsvCurvePlane(m_edit->size(), QColor::fromHsv(200, 200, 200), ColorTools::COM_H, ColorTools::COM_H)));
0267 } else if (m_mode == CurveModes::Saturation) {
0268 m_edit->setPixmap(QPixmap());
0269 } else {
0270 auto color = modeToColorsRGB(m_mode);
0271 m_edit->setPixmap(QPixmap::fromImage(ColorTools::rgbCurvePlane(m_edit->size(), color, 1, palette().window().color().rgb())));
0272 }
0273 } else {
0274 m_edit->setPixmap(QPixmap());
0275 }
0276 }
0277
0278 template <> void CurveParamWidget<BezierSplineEditor>::slotUpdatePointEntries(const BPoint &p, bool extremal)
0279 {
0280 blockSignals(true);
0281 if (p == BPoint()) {
0282 m_ui.widgetPoint->setEnabled(false);
0283 } else {
0284 m_ui.widgetPoint->setEnabled(true);
0285 // disable irrelevant buttons if the point is extremal
0286 m_pX->setEnabled(!extremal);
0287 m_ui.buttonDeletePoint->setEnabled(!extremal);
0288 m_ui.buttonLinkHandles->setEnabled(!extremal);
0289 if (extremal && p.p.x() + 1e-4 >= 1.00) { // last point
0290 m_h2X->setEnabled(false);
0291 m_h2Y->setEnabled(false);
0292 } else {
0293 m_h2X->setEnabled(true);
0294 m_h2Y->setEnabled(true);
0295 }
0296 if (extremal && p.p.x() <= 0.01) { // first point
0297 m_h1X->setEnabled(false);
0298 m_h1Y->setEnabled(false);
0299 } else {
0300 m_h1X->setEnabled(true);
0301 m_h1Y->setEnabled(true);
0302 }
0303
0304 for (auto elem : {m_pX, m_pY, m_h1X, m_h1Y, m_h2X, m_h2Y}) {
0305 elem->blockSignals(true);
0306 }
0307 m_pX->setValue(p.p.x());
0308 m_pY->setValue(p.p.y());
0309 m_h1X->setValue(p.h1.x());
0310 m_h1Y->setValue(p.h1.y());
0311 m_h2X->setValue(p.h2.x());
0312 m_h2Y->setValue(p.h2.y());
0313 for (auto elem : {m_pX, m_pY, m_h1X, m_h1Y, m_h2X, m_h2Y}) {
0314 elem->blockSignals(false);
0315 }
0316 m_ui.buttonLinkHandles->setChecked(p.handlesLinked);
0317 }
0318 blockSignals(false);
0319 }
0320
0321 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::slotUpdatePointEntries(const BPoint &p, bool extremal)
0322 {
0323 Q_UNUSED(p);
0324 Q_UNUSED(extremal);
0325 // Wrong slot called in curve widget
0326 Q_ASSERT(false);
0327 }
0328
0329 template <> void CurveParamWidget<KisCurveWidget>::slotUpdatePointEntries(const QPointF &p, bool extremal)
0330 {
0331 blockSignals(true);
0332 if (p == QPointF()) {
0333 m_ui.widgetPoint->setEnabled(false);
0334 } else {
0335 m_ui.widgetPoint->setEnabled(true);
0336 // disable irrelevant buttons if the point is extremal
0337 m_pX->setEnabled(!extremal);
0338 m_ui.buttonDeletePoint->setEnabled(!extremal);
0339
0340 for (auto elem : {m_pX, m_pY}) {
0341 elem->blockSignals(true);
0342 }
0343 m_pX->setValue(p.x());
0344 m_pY->setValue(p.y());
0345 for (auto elem : {m_pX, m_pY}) {
0346 elem->blockSignals(false);
0347 }
0348 }
0349 blockSignals(false);
0350 }
0351
0352 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::slotUpdatePointEntries(const QPointF &p, bool extremal)
0353 {
0354 Q_UNUSED(p);
0355 Q_UNUSED(extremal);
0356 // Wrong slot called in curve widget
0357 Q_ASSERT(false);
0358 }
0359
0360 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::slotShowComment(bool show)
0361 {
0362 Q_UNUSED(show);
0363 }
0364
0365 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::slotRefresh()
0366 {
0367 if (m_model->data(m_index, AssetParameterModel::TypeRole).template value<ParamType>() == ParamType::Curve) {
0368 QList<QPointF> points;
0369 int number = qRound(m_model->data(m_index, AssetParameterModel::Enum3Role).toDouble() * 10);
0370 int start = m_model->data(m_index, AssetParameterModel::MinRole).toInt();
0371 // for the curve, inpoints are numbered: 6, 8, 10, 12, 14
0372 // outpoints, 7, 9, 11, 13,15 so we need to deduce these enums
0373 int inRef = int(AssetParameterModel::Enum6Role) + 2 * (start - 1);
0374 int outRef = int(AssetParameterModel::Enum7Role) + 2 * (start - 1);
0375 for (int j = start; j <= number; ++j) {
0376 double inVal = m_model->data(m_index, AssetParameterModel::DataRoles(inRef)).toDouble();
0377 double outVal = m_model->data(m_index, AssetParameterModel::DataRoles(outRef)).toDouble();
0378 points << QPointF(inVal, outVal);
0379 inRef += 2;
0380 outRef += 2;
0381 }
0382 if (!points.isEmpty()) {
0383 m_edit->setFromString(KisCubicCurve(points).toString());
0384 }
0385 } else {
0386 m_edit->setFromString(m_model->data(m_index, AssetParameterModel::ValueRole).toString());
0387 }
0388 }
0389
0390 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::setMaxPoints(int max)
0391 {
0392 m_edit->setMaxPoints(max);
0393 }
0394
0395 template <typename CurveWidget_t> void CurveParamWidget<CurveWidget_t>::resizeEvent(QResizeEvent *e)
0396 {
0397 QWidget::resizeEvent(e);
0398 Q_EMIT updateHeight();
0399 }