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 }